[{"data":1,"prerenderedAt":3908},["ShallowReactive",2],{"/en-us/blog/tags/devsecops/":3,"navigation-en-us":20,"banner-en-us":433,"footer-en-us":446,"DevSecOps-tag-page-en-us":658},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"content":8,"config":11,"_id":13,"_type":14,"title":15,"_source":16,"_file":17,"_stem":18,"_extension":19},"/en-us/blog/tags/devsecops","tags",false,"",{"tag":9,"tagSlug":10},"DevSecOps","devsecops",{"template":12},"BlogTag","content:en-us:blog:tags:devsecops.yml","yaml","Devsecops","content","en-us/blog/tags/devsecops.yml","en-us/blog/tags/devsecops","yml",{"_path":21,"_dir":22,"_draft":6,"_partial":6,"_locale":7,"data":23,"_id":429,"_type":14,"title":430,"_source":16,"_file":431,"_stem":432,"_extension":19},"/shared/en-us/main-navigation","en-us",{"logo":24,"freeTrial":29,"sales":34,"login":39,"items":44,"search":375,"minimal":406,"duo":420},{"config":25},{"href":26,"dataGaName":27,"dataGaLocation":28},"/","gitlab logo","header",{"text":30,"config":31},"Get free trial",{"href":32,"dataGaName":33,"dataGaLocation":28},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":35,"config":36},"Talk to sales",{"href":37,"dataGaName":38,"dataGaLocation":28},"/sales/","sales",{"text":40,"config":41},"Sign in",{"href":42,"dataGaName":43,"dataGaLocation":28},"https://gitlab.com/users/sign_in/","sign in",[45,89,185,190,296,356],{"text":46,"config":47,"cards":49,"footer":72},"Platform",{"dataNavLevelOne":48},"platform",[50,56,64],{"title":46,"description":51,"link":52},"The most comprehensive AI-powered DevSecOps Platform",{"text":53,"config":54},"Explore our Platform",{"href":55,"dataGaName":48,"dataGaLocation":28},"/platform/",{"title":57,"description":58,"link":59},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":60,"config":61},"Meet GitLab Duo",{"href":62,"dataGaName":63,"dataGaLocation":28},"/gitlab-duo/","gitlab duo ai",{"title":65,"description":66,"link":67},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":68,"config":69},"Learn more",{"href":70,"dataGaName":71,"dataGaLocation":28},"/why-gitlab/","why gitlab",{"title":73,"items":74},"Get started with",[75,80,85],{"text":76,"config":77},"Platform Engineering",{"href":78,"dataGaName":79,"dataGaLocation":28},"/solutions/platform-engineering/","platform engineering",{"text":81,"config":82},"Developer Experience",{"href":83,"dataGaName":84,"dataGaLocation":28},"/developer-experience/","Developer experience",{"text":86,"config":87},"MLOps",{"href":88,"dataGaName":86,"dataGaLocation":28},"/topics/devops/the-role-of-ai-in-devops/",{"text":90,"left":91,"config":92,"link":94,"lists":98,"footer":167},"Product",true,{"dataNavLevelOne":93},"solutions",{"text":95,"config":96},"View all Solutions",{"href":97,"dataGaName":93,"dataGaLocation":28},"/solutions/",[99,124,146],{"title":100,"description":101,"link":102,"items":107},"Automation","CI/CD and automation to accelerate deployment",{"config":103},{"icon":104,"href":105,"dataGaName":106,"dataGaLocation":28},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[108,112,116,120],{"text":109,"config":110},"CI/CD",{"href":111,"dataGaLocation":28,"dataGaName":109},"/solutions/continuous-integration/",{"text":113,"config":114},"AI-Assisted Development",{"href":62,"dataGaLocation":28,"dataGaName":115},"AI assisted development",{"text":117,"config":118},"Source Code Management",{"href":119,"dataGaLocation":28,"dataGaName":117},"/solutions/source-code-management/",{"text":121,"config":122},"Automated Software Delivery",{"href":105,"dataGaLocation":28,"dataGaName":123},"Automated software delivery",{"title":125,"description":126,"link":127,"items":132},"Security","Deliver code faster without compromising security",{"config":128},{"href":129,"dataGaName":130,"dataGaLocation":28,"icon":131},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[133,136,141],{"text":134,"config":135},"Security & Compliance",{"href":129,"dataGaLocation":28,"dataGaName":134},{"text":137,"config":138},"Software Supply Chain Security",{"href":139,"dataGaLocation":28,"dataGaName":140},"/solutions/supply-chain/","Software supply chain security",{"text":142,"config":143},"Compliance & Governance",{"href":144,"dataGaLocation":28,"dataGaName":145},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":147,"link":148,"items":153},"Measurement",{"config":149},{"icon":150,"href":151,"dataGaName":152,"dataGaLocation":28},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[154,158,162],{"text":155,"config":156},"Visibility & Measurement",{"href":151,"dataGaLocation":28,"dataGaName":157},"Visibility and Measurement",{"text":159,"config":160},"Value Stream Management",{"href":161,"dataGaLocation":28,"dataGaName":159},"/solutions/value-stream-management/",{"text":163,"config":164},"Analytics & Insights",{"href":165,"dataGaLocation":28,"dataGaName":166},"/solutions/analytics-and-insights/","Analytics and insights",{"title":168,"items":169},"GitLab for",[170,175,180],{"text":171,"config":172},"Enterprise",{"href":173,"dataGaLocation":28,"dataGaName":174},"/enterprise/","enterprise",{"text":176,"config":177},"Small Business",{"href":178,"dataGaLocation":28,"dataGaName":179},"/small-business/","small business",{"text":181,"config":182},"Public Sector",{"href":183,"dataGaLocation":28,"dataGaName":184},"/solutions/public-sector/","public sector",{"text":186,"config":187},"Pricing",{"href":188,"dataGaName":189,"dataGaLocation":28,"dataNavLevelOne":189},"/pricing/","pricing",{"text":191,"config":192,"link":194,"lists":198,"feature":283},"Resources",{"dataNavLevelOne":193},"resources",{"text":195,"config":196},"View all resources",{"href":197,"dataGaName":193,"dataGaLocation":28},"/resources/",[199,232,255],{"title":200,"items":201},"Getting started",[202,207,212,217,222,227],{"text":203,"config":204},"Install",{"href":205,"dataGaName":206,"dataGaLocation":28},"/install/","install",{"text":208,"config":209},"Quick start guides",{"href":210,"dataGaName":211,"dataGaLocation":28},"/get-started/","quick setup checklists",{"text":213,"config":214},"Learn",{"href":215,"dataGaLocation":28,"dataGaName":216},"https://university.gitlab.com/","learn",{"text":218,"config":219},"Product documentation",{"href":220,"dataGaName":221,"dataGaLocation":28},"https://docs.gitlab.com/","product documentation",{"text":223,"config":224},"Best practice videos",{"href":225,"dataGaName":226,"dataGaLocation":28},"/getting-started-videos/","best practice videos",{"text":228,"config":229},"Integrations",{"href":230,"dataGaName":231,"dataGaLocation":28},"/integrations/","integrations",{"title":233,"items":234},"Discover",[235,240,245,250],{"text":236,"config":237},"Customer success stories",{"href":238,"dataGaName":239,"dataGaLocation":28},"/customers/","customer success stories",{"text":241,"config":242},"Blog",{"href":243,"dataGaName":244,"dataGaLocation":28},"/blog/","blog",{"text":246,"config":247},"Remote",{"href":248,"dataGaName":249,"dataGaLocation":28},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":251,"config":252},"TeamOps",{"href":253,"dataGaName":254,"dataGaLocation":28},"/teamops/","teamops",{"title":256,"items":257},"Connect",[258,263,268,273,278],{"text":259,"config":260},"GitLab Services",{"href":261,"dataGaName":262,"dataGaLocation":28},"/services/","services",{"text":264,"config":265},"Community",{"href":266,"dataGaName":267,"dataGaLocation":28},"/community/","community",{"text":269,"config":270},"Forum",{"href":271,"dataGaName":272,"dataGaLocation":28},"https://forum.gitlab.com/","forum",{"text":274,"config":275},"Events",{"href":276,"dataGaName":277,"dataGaLocation":28},"/events/","events",{"text":279,"config":280},"Partners",{"href":281,"dataGaName":282,"dataGaLocation":28},"/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":28},"/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":28},"/company/","about",{"text":309,"config":310,"footerGa":313},"Jobs",{"href":311,"dataGaName":312,"dataGaLocation":28},"/jobs/","jobs",{"dataGaName":312},{"text":274,"config":315},{"href":276,"dataGaName":277,"dataGaLocation":28},{"text":317,"config":318},"Leadership",{"href":319,"dataGaName":320,"dataGaLocation":28},"/company/team/e-group/","leadership",{"text":322,"config":323},"Team",{"href":324,"dataGaName":325,"dataGaLocation":28},"/company/team/","team",{"text":327,"config":328},"Handbook",{"href":329,"dataGaName":330,"dataGaLocation":28},"https://handbook.gitlab.com/","handbook",{"text":332,"config":333},"Investor relations",{"href":334,"dataGaName":335,"dataGaLocation":28},"https://ir.gitlab.com/","investor relations",{"text":337,"config":338},"Trust Center",{"href":339,"dataGaName":340,"dataGaLocation":28},"/security/","trust center",{"text":342,"config":343},"AI Transparency Center",{"href":344,"dataGaName":345,"dataGaLocation":28},"/ai-transparency-center/","ai transparency center",{"text":347,"config":348},"Newsletter",{"href":349,"dataGaName":350,"dataGaLocation":28},"/company/contact/","newsletter",{"text":352,"config":353},"Press",{"href":354,"dataGaName":355,"dataGaLocation":28},"/press/","press",{"text":357,"config":358,"lists":359},"Contact us",{"dataNavLevelOne":299},[360],{"items":361},[362,365,370],{"text":35,"config":363},{"href":37,"dataGaName":364,"dataGaLocation":28},"talk to sales",{"text":366,"config":367},"Get help",{"href":368,"dataGaName":369,"dataGaLocation":28},"/support/","get help",{"text":371,"config":372},"Customer portal",{"href":373,"dataGaName":374,"dataGaLocation":28},"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":42,"dataGaName":382,"dataGaLocation":383},"search login","search",{"text":385,"default":386},"Suggestions",[387,389,393,395,399,403],{"text":57,"config":388},{"href":62,"dataGaName":57,"dataGaLocation":383},{"text":390,"config":391},"Code Suggestions (AI)",{"href":392,"dataGaName":390,"dataGaLocation":383},"/solutions/code-suggestions/",{"text":109,"config":394},{"href":111,"dataGaName":109,"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":70,"dataGaName":404,"dataGaLocation":383},{"freeTrial":407,"mobileIcon":412,"desktopIcon":417},{"text":408,"config":409},"Start free trial",{"href":410,"dataGaName":33,"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",{"freeTrial":421,"mobileIcon":425,"desktopIcon":427},{"text":422,"config":423},"Learn more about GitLab Duo",{"href":62,"dataGaName":424,"dataGaLocation":411},"gitlab duo",{"altText":413,"config":426},{"src":415,"dataGaName":416,"dataGaLocation":411},{"altText":413,"config":428},{"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":434,"_dir":22,"_draft":6,"_partial":6,"_locale":7,"title":435,"titleMobile":435,"button":436,"config":441,"_id":443,"_type":14,"_source":16,"_file":444,"_stem":445,"_extension":19},"/shared/en-us/banner","GitLab 18 & the next step in intelligent DevSecOps.",{"text":437,"config":438},"Watch now",{"href":439,"dataGaName":440,"dataGaLocation":28},"/eighteen/","gitlab 18 banner",{"layout":442},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":447,"_dir":22,"_draft":6,"_partial":6,"_locale":7,"data":448,"_id":654,"_type":14,"title":655,"_source":16,"_file":656,"_stem":657,"_extension":19},"/shared/en-us/main-footer",{"text":449,"source":450,"edit":456,"contribute":461,"config":466,"items":471,"minimal":646},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":451,"config":452},"View page source",{"href":453,"dataGaName":454,"dataGaLocation":455},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":457,"config":458},"Edit this page",{"href":459,"dataGaName":460,"dataGaLocation":455},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":462,"config":463},"Please contribute",{"href":464,"dataGaName":465,"dataGaLocation":455},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":467,"facebook":468,"youtube":469,"linkedin":470},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[472,495,552,581,616],{"title":46,"links":473,"subMenu":478},[474],{"text":475,"config":476},"DevSecOps platform",{"href":55,"dataGaName":477,"dataGaLocation":455},"devsecops platform",[479],{"title":186,"links":480},[481,485,490],{"text":482,"config":483},"View plans",{"href":188,"dataGaName":484,"dataGaLocation":455},"view plans",{"text":486,"config":487},"Why Premium?",{"href":488,"dataGaName":489,"dataGaLocation":455},"/pricing/premium/","why premium",{"text":491,"config":492},"Why Ultimate?",{"href":493,"dataGaName":494,"dataGaLocation":455},"/pricing/ultimate/","why ultimate",{"title":496,"links":497},"Solutions",[498,503,506,508,513,518,522,525,529,534,536,539,542,547],{"text":499,"config":500},"Digital transformation",{"href":501,"dataGaName":502,"dataGaLocation":455},"/solutions/digital-transformation/","digital transformation",{"text":134,"config":504},{"href":129,"dataGaName":505,"dataGaLocation":455},"security & compliance",{"text":123,"config":507},{"href":105,"dataGaName":106,"dataGaLocation":455},{"text":509,"config":510},"Agile development",{"href":511,"dataGaName":512,"dataGaLocation":455},"/solutions/agile-delivery/","agile delivery",{"text":514,"config":515},"Cloud transformation",{"href":516,"dataGaName":517,"dataGaLocation":455},"/topics/cloud-native/","cloud transformation",{"text":519,"config":520},"SCM",{"href":119,"dataGaName":521,"dataGaLocation":455},"source code management",{"text":109,"config":523},{"href":111,"dataGaName":524,"dataGaLocation":455},"continuous integration & delivery",{"text":526,"config":527},"Value stream management",{"href":161,"dataGaName":528,"dataGaLocation":455},"value stream management",{"text":530,"config":531},"GitOps",{"href":532,"dataGaName":533,"dataGaLocation":455},"/solutions/gitops/","gitops",{"text":171,"config":535},{"href":173,"dataGaName":174,"dataGaLocation":455},{"text":537,"config":538},"Small business",{"href":178,"dataGaName":179,"dataGaLocation":455},{"text":540,"config":541},"Public sector",{"href":183,"dataGaName":184,"dataGaLocation":455},{"text":543,"config":544},"Education",{"href":545,"dataGaName":546,"dataGaLocation":455},"/solutions/education/","education",{"text":548,"config":549},"Financial services",{"href":550,"dataGaName":551,"dataGaLocation":455},"/solutions/finance/","financial services",{"title":191,"links":553},[554,556,558,560,563,565,567,569,571,573,575,577,579],{"text":203,"config":555},{"href":205,"dataGaName":206,"dataGaLocation":455},{"text":208,"config":557},{"href":210,"dataGaName":211,"dataGaLocation":455},{"text":213,"config":559},{"href":215,"dataGaName":216,"dataGaLocation":455},{"text":218,"config":561},{"href":220,"dataGaName":562,"dataGaLocation":455},"docs",{"text":241,"config":564},{"href":243,"dataGaName":244,"dataGaLocation":455},{"text":236,"config":566},{"href":238,"dataGaName":239,"dataGaLocation":455},{"text":246,"config":568},{"href":248,"dataGaName":249,"dataGaLocation":455},{"text":259,"config":570},{"href":261,"dataGaName":262,"dataGaLocation":455},{"text":251,"config":572},{"href":253,"dataGaName":254,"dataGaLocation":455},{"text":264,"config":574},{"href":266,"dataGaName":267,"dataGaLocation":455},{"text":269,"config":576},{"href":271,"dataGaName":272,"dataGaLocation":455},{"text":274,"config":578},{"href":276,"dataGaName":277,"dataGaLocation":455},{"text":279,"config":580},{"href":281,"dataGaName":282,"dataGaLocation":455},{"title":297,"links":582},[583,585,587,589,591,593,595,600,605,607,609,611],{"text":304,"config":584},{"href":306,"dataGaName":299,"dataGaLocation":455},{"text":309,"config":586},{"href":311,"dataGaName":312,"dataGaLocation":455},{"text":317,"config":588},{"href":319,"dataGaName":320,"dataGaLocation":455},{"text":322,"config":590},{"href":324,"dataGaName":325,"dataGaLocation":455},{"text":327,"config":592},{"href":329,"dataGaName":330,"dataGaLocation":455},{"text":332,"config":594},{"href":334,"dataGaName":335,"dataGaLocation":455},{"text":596,"config":597},"Environmental, social and governance (ESG)",{"href":598,"dataGaName":599,"dataGaLocation":455},"/environmental-social-governance/","environmental, social and governance",{"text":601,"config":602},"Diversity, inclusion and belonging (DIB)",{"href":603,"dataGaName":604,"dataGaLocation":455},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":337,"config":606},{"href":339,"dataGaName":340,"dataGaLocation":455},{"text":347,"config":608},{"href":349,"dataGaName":350,"dataGaLocation":455},{"text":352,"config":610},{"href":354,"dataGaName":355,"dataGaLocation":455},{"text":612,"config":613},"Modern Slavery Transparency Statement",{"href":614,"dataGaName":615,"dataGaLocation":455},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":617,"links":618},"Contact Us",[619,622,624,626,631,636,641],{"text":620,"config":621},"Contact an expert",{"href":37,"dataGaName":38,"dataGaLocation":455},{"text":366,"config":623},{"href":368,"dataGaName":369,"dataGaLocation":455},{"text":371,"config":625},{"href":373,"dataGaName":374,"dataGaLocation":455},{"text":627,"config":628},"Status",{"href":629,"dataGaName":630,"dataGaLocation":455},"https://status.gitlab.com/","status",{"text":632,"config":633},"Terms of use",{"href":634,"dataGaName":635,"dataGaLocation":455},"/terms/","terms of use",{"text":637,"config":638},"Privacy statement",{"href":639,"dataGaName":640,"dataGaLocation":455},"/privacy/","privacy statement",{"text":642,"config":643},"Cookie preferences",{"dataGaName":644,"dataGaLocation":455,"id":645,"isOneTrustButton":91},"cookie preferences","ot-sdk-btn",{"items":647},[648,650,652],{"text":632,"config":649},{"href":634,"dataGaName":635,"dataGaLocation":455},{"text":637,"config":651},{"href":639,"dataGaName":640,"dataGaLocation":455},{"text":642,"config":653},{"dataGaName":644,"dataGaLocation":455,"id":645,"isOneTrustButton":91},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",{"allPosts":659,"featuredPost":3888,"totalPagesCount":3906,"initialPosts":3907},[660,684,707,727,749,770,791,815,836,856,877,898,918,941,962,983,1004,1029,1050,1072,1092,1112,1130,1148,1166,1186,1206,1226,1247,1266,1287,1309,1328,1347,1365,1387,1406,1425,1446,1466,1487,1504,1525,1545,1564,1583,1603,1623,1642,1662,1681,1702,1722,1742,1762,1781,1799,1818,1838,1859,1878,1896,1915,1933,1952,1972,1990,2010,2030,2050,2072,2093,2112,2133,2151,2170,2188,2206,2224,2245,2264,2283,2302,2321,2340,2359,2378,2397,2416,2434,2455,2475,2493,2512,2532,2551,2571,2591,2609,2628,2647,2666,2684,2703,2722,2742,2762,2782,2802,2820,2839,2858,2877,2896,2914,2932,2951,2973,2992,3011,3029,3048,3067,3087,3107,3127,3147,3164,3183,3201,3221,3242,3260,3280,3300,3319,3337,3356,3374,3394,3412,3431,3449,3468,3487,3507,3525,3543,3565,3583,3603,3621,3639,3657,3675,3694,3714,3734,3753,3772,3792,3812,3831,3852,3870],{"_path":661,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":662,"content":670,"config":677,"_id":680,"_type":14,"title":681,"_source":16,"_file":682,"_stem":683,"_extension":19},"/en-us/blog/3-tips-to-improve-your-security-risk-management-program",{"title":663,"description":664,"ogTitle":663,"ogDescription":664,"noIndex":6,"ogImage":665,"ogUrl":666,"ogSiteName":667,"ogType":668,"canonicalUrls":666,"schema":669},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749665667/Blog/Hero%20Images/built-in-security.jpg","https://about.gitlab.com/blog/3-tips-to-improve-your-security-risk-management-program","https://about.gitlab.com","article","\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":663,"description":664,"authors":671,"heroImage":665,"date":673,"body":674,"category":675,"tags":676},[672],"Kyle Smith","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.","security",[675,9],{"slug":678,"featured":91,"template":679},"3-tips-to-improve-your-security-risk-management-program","BlogPost","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":685,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":686,"content":692,"config":701,"_id":703,"_type":14,"title":704,"_source":16,"_file":705,"_stem":706,"_extension":19},"/en-us/blog/5-things-to-know-from-our-linkedin-live-security-deep-dive",{"title":687,"description":688,"ogTitle":687,"ogDescription":688,"noIndex":6,"ogImage":689,"ogUrl":690,"ogSiteName":667,"ogType":668,"canonicalUrls":690,"schema":691},"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":687,"description":688,"authors":693,"heroImage":689,"date":695,"body":696,"category":675,"tags":697},[694],"Fatima Sarah Khalid","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.",[698,675,699,9,700],"AI/ML","webcast","features",{"slug":702,"featured":91,"template":679},"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":708,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":709,"content":715,"config":721,"_id":723,"_type":14,"title":724,"_source":16,"_file":725,"_stem":726,"_extension":19},"/en-us/blog/7-steps-to-enhance-application-security-without-slowing-developer-velocity",{"title":710,"description":711,"ogTitle":710,"ogDescription":711,"noIndex":6,"ogImage":712,"ogUrl":713,"ogSiteName":667,"ogType":668,"canonicalUrls":713,"schema":714},"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":710,"description":711,"authors":716,"heroImage":712,"date":718,"body":719,"category":675,"tags":720},[717],"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).",[675,9],{"slug":722,"featured":91,"template":679},"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":728,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":729,"content":735,"config":743,"_id":745,"_type":14,"title":746,"_source":16,"_file":747,"_stem":748,"_extension":19},"/en-us/blog/7-tips-on-how-to-successfully-talk-to-execs-about-devsecops",{"title":730,"description":731,"ogTitle":730,"ogDescription":731,"noIndex":6,"ogImage":732,"ogUrl":733,"ogSiteName":667,"ogType":668,"canonicalUrls":733,"schema":734},"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":730,"description":731,"authors":736,"heroImage":732,"date":738,"body":739,"category":10,"tags":740},[737],"Sharon Gaudin","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",[9,741,742],"collaboration","careers",{"slug":744,"featured":6,"template":679},"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":750,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":751,"content":757,"config":764,"_id":766,"_type":14,"title":767,"_source":16,"_file":768,"_stem":769,"_extension":19},"/en-us/blog/a-developers-guide-to-building-an-ai-security-governance-framework",{"title":752,"description":753,"ogTitle":752,"ogDescription":753,"noIndex":6,"ogImage":754,"ogUrl":755,"ogSiteName":667,"ogType":668,"canonicalUrls":755,"schema":756},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749664638/Blog/Hero%20Images/applicationsecurity.png","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":752,"description":753,"authors":758,"heroImage":754,"date":760,"body":761,"category":762,"tags":763},[759],"Ayoub Fandi","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","ai-ml",[698,9,675,184],{"slug":765,"featured":91,"template":679},"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":771,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":772,"content":778,"config":785,"_id":787,"_type":14,"title":788,"_source":16,"_file":789,"_stem":790,"_extension":19},"/en-us/blog/achieve-slsa-level-2-compliance-with-gitlab",{"title":773,"description":774,"ogTitle":773,"ogDescription":774,"noIndex":6,"ogImage":775,"ogUrl":776,"ogSiteName":667,"ogType":668,"canonicalUrls":776,"schema":777},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749667094/Blog/Hero%20Images/container-security.jpg","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":773,"description":774,"authors":779,"heroImage":775,"date":781,"body":782,"category":675,"tags":783},[780],"Sandra Gittlen","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",[9,675,784,184],"open source",{"slug":786,"featured":6,"template":679},"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":792,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":793,"content":799,"config":809,"_id":811,"_type":14,"title":812,"_source":16,"_file":813,"_stem":814,"_extension":19},"/en-us/blog/actioning-security-vulnerabilities-in-gitlab-premium",{"title":794,"description":795,"ogTitle":794,"ogDescription":795,"noIndex":6,"ogImage":796,"ogUrl":797,"ogSiteName":667,"ogType":668,"canonicalUrls":797,"schema":798},"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":794,"description":795,"authors":800,"heroImage":796,"date":803,"body":804,"category":675,"tags":805},[801,802],"Sam Morris","Noah Ing","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)._",[675,9,806,807,808],"CI","CD","tutorial",{"slug":810,"featured":6,"template":679},"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":816,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":817,"content":823,"config":830,"_id":832,"_type":14,"title":833,"_source":16,"_file":834,"_stem":835,"_extension":19},"/en-us/blog/ai-assisted-code-suggestions",{"title":818,"description":819,"ogTitle":818,"ogDescription":819,"noIndex":6,"ogImage":820,"ogUrl":821,"ogSiteName":667,"ogType":668,"canonicalUrls":821,"schema":822},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749662840/Blog/Hero%20Images/ai-experiment-stars.png","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":818,"description":819,"authors":824,"heroImage":820,"date":826,"body":827,"category":762,"tags":828},[825],"Neha Khalwadekar","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",[9,829,700,698],"product",{"slug":831,"featured":6,"template":679},"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":837,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":838,"content":844,"config":850,"_id":852,"_type":14,"title":853,"_source":16,"_file":854,"_stem":855,"_extension":19},"/en-us/blog/announcing-gitlab-devsecops",{"title":839,"description":840,"ogTitle":839,"ogDescription":840,"noIndex":6,"ogImage":841,"ogUrl":842,"ogSiteName":667,"ogType":668,"canonicalUrls":842,"schema":843},"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":839,"description":840,"authors":845,"heroImage":841,"date":847,"body":848,"category":299,"tags":849},[846],"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](/features/#secure) 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",[530,9],{"slug":851,"featured":6,"template":679},"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":857,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":858,"content":864,"config":871,"_id":873,"_type":14,"title":874,"_source":16,"_file":875,"_stem":876,"_extension":19},"/en-us/blog/atlassian-server-ending-move-to-a-single-devsecops-platform",{"title":859,"description":860,"ogTitle":859,"ogDescription":860,"noIndex":6,"ogImage":861,"ogUrl":862,"ogSiteName":667,"ogType":668,"canonicalUrls":862,"schema":863},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749658924/Blog/Hero%20Images/securitylifecycle-light.png","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":865,"description":860,"authors":866,"heroImage":861,"date":868,"body":869,"category":10,"tags":870},"Atlassian Server ending: Goodbye disjointed toolchain, hello DevSecOps platform",[867],"Dave Steer","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",[9,109,675],{"slug":872,"featured":6,"template":679},"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":878,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":879,"content":885,"config":892,"_id":894,"_type":14,"title":895,"_source":16,"_file":896,"_stem":897,"_extension":19},"/en-us/blog/automating-a-twitter-bot-using-gitlab-cicd",{"title":880,"description":881,"ogTitle":880,"ogDescription":881,"noIndex":6,"ogImage":882,"ogUrl":883,"ogSiteName":667,"ogType":668,"canonicalUrls":883,"schema":884},"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":880,"description":881,"authors":886,"heroImage":882,"date":888,"body":889,"category":890,"tags":891},[887],"Siddharth Mathur","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","engineering",[9,806,807,808],{"slug":893,"featured":6,"template":679},"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":899,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":900,"content":906,"config":912,"_id":914,"_type":14,"title":915,"_source":16,"_file":916,"_stem":917,"_extension":19},"/en-us/blog/automating-cybersecurity-threat-detections-with-gitlab-ci-cd",{"title":901,"description":902,"ogTitle":901,"ogDescription":902,"noIndex":6,"ogImage":903,"ogUrl":904,"ogSiteName":667,"ogType":668,"canonicalUrls":904,"schema":905},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749663239/Blog/Hero%20Images/AdobeStock_1023776629.jpg","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":901,"description":902,"authors":907,"heroImage":903,"date":909,"body":910,"category":675,"tags":911},[908],"Mitra Jozenazemian","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/).",[675,808,9,475,109],{"slug":913,"featured":6,"template":679},"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":919,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":920,"content":926,"config":935,"_id":937,"_type":14,"title":938,"_source":16,"_file":939,"_stem":940,"_extension":19},"/en-us/blog/best-practices-leading-orgs-to-release-software-faster",{"title":921,"description":922,"ogTitle":921,"ogDescription":922,"noIndex":6,"ogImage":923,"ogUrl":924,"ogSiteName":667,"ogType":668,"canonicalUrls":924,"schema":925},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749663908/Blog/Hero%20Images/2023-devsecops-report-blog-banner2.png","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":921,"description":922,"authors":927,"heroImage":923,"date":929,"body":930,"category":931,"tags":932},[928],"Kristina Weis","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","insights",[933,109,934,9],"developer survey","cloud native",{"slug":936,"featured":6,"template":679},"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":942,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":943,"content":949,"config":956,"_id":958,"_type":14,"title":959,"_source":16,"_file":960,"_stem":961,"_extension":19},"/en-us/blog/betstudios-cto-on-improving-ci-cd-capabilities-with-gitlab-premium",{"title":944,"description":945,"ogTitle":944,"ogDescription":945,"noIndex":6,"ogImage":946,"ogUrl":947,"ogSiteName":667,"ogType":668,"canonicalUrls":947,"schema":948},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749663000/Blog/Hero%20Images/tanukilifecycle.png","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":944,"description":945,"authors":950,"heroImage":946,"date":951,"body":952,"category":953,"tags":954},[928],"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/).","customer-stories",[9,475,109,955],"customers",{"slug":957,"featured":6,"template":679},"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":963,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":964,"content":970,"config":977,"_id":979,"_type":14,"title":980,"_source":16,"_file":981,"_stem":982,"_extension":19},"/en-us/blog/building-a-more-inclusive-and-welcoming-open-source-community-on-gitlab",{"title":965,"description":966,"ogTitle":965,"ogDescription":966,"noIndex":6,"ogImage":967,"ogUrl":968,"ogSiteName":667,"ogType":668,"canonicalUrls":968,"schema":969},"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":965,"description":966,"authors":971,"heroImage":967,"date":973,"body":974,"category":975,"tags":976},[972],"Emilio Salvador","2024-01-29","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.","news",[975,475,9],{"slug":978,"featured":6,"template":679},"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":984,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":985,"content":991,"config":998,"_id":1000,"_type":14,"title":1001,"_source":16,"_file":1002,"_stem":1003,"_extension":19},"/en-us/blog/building-a-text-adventure-using-cplusplus-and-code-suggestions",{"title":986,"description":987,"ogTitle":986,"ogDescription":987,"noIndex":6,"ogImage":988,"ogUrl":989,"ogSiteName":667,"ogType":668,"canonicalUrls":989,"schema":990},"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":992,"description":987,"authors":993,"heroImage":988,"date":994,"body":995,"category":762,"tags":996},"Explore the Dragon Realm: Build a C++ adventure game with a little help from AI",[694],"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",[475,698,997,9,808],"workflow",{"slug":999,"featured":6,"template":679},"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":1005,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1006,"content":1012,"config":1023,"_id":1025,"_type":14,"title":1026,"_source":16,"_file":1027,"_stem":1028,"_extension":19},"/en-us/blog/building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features",{"title":1007,"description":1008,"ogTitle":1007,"ogDescription":1008,"noIndex":6,"ogImage":1009,"ogUrl":1010,"ogSiteName":667,"ogType":668,"canonicalUrls":1010,"schema":1011},"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":1007,"description":1008,"authors":1013,"heroImage":1009,"date":1016,"body":1017,"category":890,"tags":1018},[1014,1015],"Chance Feick","Sam Wiskow","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",[109,807,806,1019,808,1020,1021,1022,9,698],"inside GitLab","performance","google","git",{"slug":1024,"featured":91,"template":679},"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":1030,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1031,"content":1037,"config":1044,"_id":1046,"_type":14,"title":1047,"_source":16,"_file":1048,"_stem":1049,"_extension":19},"/en-us/blog/building-gitlab-with-gitlab-stress-testing-product-analytics",{"title":1032,"description":1033,"ogTitle":1032,"ogDescription":1033,"noIndex":6,"ogImage":1034,"ogUrl":1035,"ogSiteName":667,"ogType":668,"canonicalUrls":1035,"schema":1036},"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://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-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":1032,"description":1033,"authors":1038,"heroImage":1034,"date":1041,"body":1042,"category":10,"tags":1043},[1039,1040],"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",[9,829,1020,1019],{"slug":1045,"featured":91,"template":679},"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":1051,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1052,"content":1057,"config":1066,"_id":1068,"_type":14,"title":1069,"_source":16,"_file":1070,"_stem":1071,"_extension":19},"/en-us/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated",{"title":1053,"description":1054,"ogTitle":1053,"ogDescription":1054,"noIndex":6,"ogImage":1034,"ogUrl":1055,"ogSiteName":667,"ogType":668,"canonicalUrls":1055,"schema":1056},"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":1053,"description":1054,"authors":1058,"heroImage":1034,"date":1062,"body":1063,"category":890,"tags":1064},[1059,1060,1061],"Andrew Newdigate","Craig Miskell","John Coghlan","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",[1065,475,9,700],"AWS",{"slug":1067,"featured":6,"template":679},"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":1073,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1074,"content":1080,"config":1086,"_id":1088,"_type":14,"title":1089,"_source":16,"_file":1090,"_stem":1091,"_extension":19},"/en-us/blog/can-your-ci-cd-environment-support-ai-powered-devsecops",{"title":1075,"description":1076,"ogTitle":1075,"ogDescription":1076,"noIndex":6,"ogImage":1077,"ogUrl":1078,"ogSiteName":667,"ogType":668,"canonicalUrls":1078,"schema":1079},"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":1075,"description":1076,"authors":1081,"heroImage":1077,"date":1083,"body":1084,"category":762,"tags":1085},[1082],"Darren Eastman","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",[109,9,698],{"slug":1087,"featured":6,"template":679},"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":1093,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1094,"content":1100,"config":1106,"_id":1108,"_type":14,"title":1109,"_source":16,"_file":1110,"_stem":1111,"_extension":19},"/en-us/blog/ci-cd-catalog-goes-ga-no-more-building-pipelines-from-scratch",{"title":1095,"description":1096,"ogTitle":1095,"ogDescription":1096,"noIndex":6,"ogImage":1097,"ogUrl":1098,"ogSiteName":667,"ogType":668,"canonicalUrls":1098,"schema":1099},"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":1095,"description":1096,"authors":1101,"heroImage":1097,"date":1103,"body":1104,"category":829,"tags":1105},[1102],"Dov Hershkovitch","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",[109,9,475,700],{"slug":1107,"featured":91,"template":679},"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":1113,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1114,"content":1119,"config":1124,"_id":1126,"_type":14,"title":1127,"_source":16,"_file":1128,"_stem":1129,"_extension":19},"/en-us/blog/code-suggestions-for-all-during-beta",{"title":1115,"description":1116,"ogTitle":1115,"ogDescription":1116,"noIndex":6,"ogImage":820,"ogUrl":1117,"ogSiteName":667,"ogType":668,"canonicalUrls":1117,"schema":1118},"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":1115,"description":1116,"authors":1120,"heroImage":820,"date":1121,"body":1122,"category":762,"tags":1123},[825],"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",[9,829,700,698],{"slug":1125,"featured":6,"template":679},"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":1131,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1132,"content":1137,"config":1142,"_id":1144,"_type":14,"title":1145,"_source":16,"_file":1146,"_stem":1147,"_extension":19},"/en-us/blog/code-suggestions-improves-developer-productivity",{"title":1133,"description":1134,"ogTitle":1133,"ogDescription":1134,"noIndex":6,"ogImage":820,"ogUrl":1135,"ogSiteName":667,"ogType":668,"canonicalUrls":1135,"schema":1136},"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":1133,"description":1134,"authors":1138,"heroImage":820,"date":1139,"body":1140,"category":762,"tags":1141},[825],"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",[9,829,700,698],{"slug":1143,"featured":6,"template":679},"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":1149,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1150,"content":1155,"config":1160,"_id":1162,"_type":14,"title":1163,"_source":16,"_file":1164,"_stem":1165,"_extension":19},"/en-us/blog/comply-with-nist-secure-supply-chain-framework-with-gitlab",{"title":1151,"description":1152,"ogTitle":1151,"ogDescription":1152,"noIndex":6,"ogImage":775,"ogUrl":1153,"ogSiteName":667,"ogType":668,"canonicalUrls":1153,"schema":1154},"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":1151,"description":1152,"authors":1156,"heroImage":775,"date":1157,"body":1158,"category":675,"tags":1159},[780],"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",[9,475,675,184],{"slug":1161,"featured":6,"template":679},"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":1167,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1168,"content":1173,"config":1180,"_id":1182,"_type":14,"title":1183,"_source":16,"_file":1184,"_stem":1185,"_extension":19},"/en-us/blog/dast-release-first-gitlab-active-check",{"title":1169,"description":1170,"ogTitle":1169,"ogDescription":1170,"noIndex":6,"ogImage":754,"ogUrl":1171,"ogSiteName":667,"ogType":668,"canonicalUrls":1171,"schema":1172},"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":1169,"description":1170,"authors":1174,"heroImage":754,"date":1176,"body":1177,"category":675,"tags":1178},[1175],"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",[9,829,1179,700,675],"testing",{"slug":1181,"featured":6,"template":679},"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":1187,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1188,"content":1194,"config":1200,"_id":1202,"_type":14,"title":1203,"_source":16,"_file":1204,"_stem":1205,"_extension":19},"/en-us/blog/data-driven-decision-making-with-sourcewarp",{"title":1189,"description":1190,"ogTitle":1189,"ogDescription":1190,"noIndex":6,"ogImage":1191,"ogUrl":1192,"ogSiteName":667,"ogType":668,"canonicalUrls":1192,"schema":1193},"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":1189,"description":1190,"authors":1195,"heroImage":1191,"date":1197,"body":1198,"category":890,"tags":1199},[1196],"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",[9,109,675],{"slug":1201,"featured":6,"template":679},"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":1207,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1208,"content":1214,"config":1220,"_id":1222,"_type":14,"title":1223,"_source":16,"_file":1224,"_stem":1225,"_extension":19},"/en-us/blog/debug-web-apps-quickly-within-gitlab",{"title":1209,"description":1210,"ogTitle":1209,"ogDescription":1210,"noIndex":6,"ogImage":1211,"ogUrl":1212,"ogSiteName":667,"ogType":668,"canonicalUrls":1212,"schema":1213},"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":1209,"description":1210,"authors":1215,"heroImage":1211,"date":1103,"body":1217,"category":890,"tags":1218},[1216],"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",[231,1219,9],"code review",{"slug":1221,"featured":6,"template":679},"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":1227,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1228,"content":1234,"config":1241,"_id":1243,"_type":14,"title":1244,"_source":16,"_file":1245,"_stem":1246,"_extension":19},"/en-us/blog/deploy-a-server-using-go-with-gitlab-google-cloud",{"title":1229,"description":1230,"ogTitle":1229,"ogDescription":1230,"noIndex":6,"ogImage":1231,"ogUrl":1232,"ogSiteName":667,"ogType":668,"canonicalUrls":1232,"schema":1233},"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":1229,"description":1230,"authors":1235,"heroImage":1231,"date":1237,"body":1238,"category":829,"tags":1239},[1236,802],"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",[9,475,808,1240,829,700],"solutions architecture",{"slug":1242,"featured":6,"template":679},"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":1248,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1249,"content":1255,"config":1260,"_id":1262,"_type":14,"title":1263,"_source":16,"_file":1264,"_stem":1265,"_extension":19},"/en-us/blog/develop-c-unit-testing-with-catch2-junit-and-gitlab-ci",{"title":1250,"description":1251,"ogTitle":1250,"ogDescription":1251,"noIndex":6,"ogImage":1252,"ogUrl":1253,"ogSiteName":667,"ogType":668,"canonicalUrls":1253,"schema":1254},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749659684/Blog/Hero%20Images/AdobeStock_479904468__1_.jpg","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":1250,"description":1251,"authors":1256,"heroImage":1252,"date":1257,"body":1258,"category":10,"tags":1259},[694],"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",[808,1179,806,698,9],{"slug":1261,"featured":91,"template":679},"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":1267,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1268,"content":1274,"config":1281,"_id":1283,"_type":14,"title":1284,"_source":16,"_file":1285,"_stem":1286,"_extension":19},"/en-us/blog/developer-relations-at-gitlab-what-weve-learned-since-our-start",{"title":1269,"description":1270,"ogTitle":1269,"ogDescription":1270,"noIndex":6,"ogImage":1271,"ogUrl":1272,"ogSiteName":667,"ogType":668,"canonicalUrls":1272,"schema":1273},"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":1269,"description":1270,"authors":1275,"heroImage":1271,"date":1276,"body":1277,"category":1278,"tags":1279},[1061],"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",[1280,9,1019],"DevOps",{"slug":1282,"featured":91,"template":679},"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":1288,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1289,"content":1295,"config":1303,"_id":1305,"_type":14,"title":1306,"_source":16,"_file":1307,"_stem":1308,"_extension":19},"/en-us/blog/developing-gitlab-duo-blending-ai-and-root-cause-analysis-to-fix-ci-cd",{"title":1290,"description":1291,"ogTitle":1290,"ogDescription":1291,"noIndex":6,"ogImage":1292,"ogUrl":1293,"ogSiteName":667,"ogType":668,"canonicalUrls":1293,"schema":1294},"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":1296,"description":1291,"authors":1297,"heroImage":1292,"date":1300,"body":1301,"category":762,"tags":1302},"Developing GitLab Duo: Blending AI and Root Cause Analysis to fix CI/CD pipelines",[1298,1299],"Rutvik Shah","Michael Friedrich","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/)",[698,808,9,475,700],{"slug":1304,"featured":91,"template":679},"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":1310,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1311,"content":1316,"config":1322,"_id":1324,"_type":14,"title":1325,"_source":16,"_file":1326,"_stem":1327,"_extension":19},"/en-us/blog/developing-gitlab-duo-how-we-validate-and-test-ai-models-at-scale",{"title":1312,"description":1313,"ogTitle":1312,"ogDescription":1313,"noIndex":6,"ogImage":689,"ogUrl":1314,"ogSiteName":667,"ogType":668,"canonicalUrls":1314,"schema":1315},"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":1312,"description":1313,"authors":1317,"heroImage":689,"date":1319,"body":1320,"category":762,"tags":1321},[1318],"Susie Bitters","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/)",[698,9,475,700,1019],{"slug":1323,"featured":91,"template":679},"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":1329,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1330,"content":1335,"config":1341,"_id":1343,"_type":14,"title":1344,"_source":16,"_file":1345,"_stem":1346,"_extension":19},"/en-us/blog/developing-gitlab-duo-series",{"title":1331,"description":1332,"ogTitle":1331,"ogDescription":1332,"noIndex":6,"ogImage":689,"ogUrl":1333,"ogSiteName":667,"ogType":668,"canonicalUrls":1333,"schema":1334},"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":1331,"description":1332,"authors":1336,"heroImage":689,"date":1338,"body":1339,"category":762,"tags":1340},[1337],"GitLab Team","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.",[698,700,9,475],{"slug":1342,"featured":6,"template":679},"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":1348,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1349,"content":1354,"config":1359,"_id":1361,"_type":14,"title":1362,"_source":16,"_file":1363,"_stem":1364,"_extension":19},"/en-us/blog/devsecops-platforms-give-smbs-security-muscle",{"title":1350,"description":1351,"ogTitle":1350,"ogDescription":1351,"noIndex":6,"ogImage":775,"ogUrl":1352,"ogSiteName":667,"ogType":668,"canonicalUrls":1352,"schema":1353},"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":1350,"description":1351,"authors":1355,"heroImage":775,"date":1356,"body":1357,"category":10,"tags":1358},[737],"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",[1280,9,675,698],{"slug":1360,"featured":6,"template":679},"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":1366,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1367,"content":1373,"config":1381,"_id":1383,"_type":14,"title":1384,"_source":16,"_file":1385,"_stem":1386,"_extension":19},"/en-us/blog/ditch-your-legacy-planning-tool-get-agile-with-gitlab",{"title":1368,"description":1369,"ogTitle":1368,"ogDescription":1369,"noIndex":6,"ogImage":1370,"ogUrl":1371,"ogSiteName":667,"ogType":668,"canonicalUrls":1371,"schema":1372},"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":1368,"description":1369,"authors":1374,"heroImage":1370,"date":1376,"body":1377,"category":1378,"tags":1379},[1375],"Amanda Rueda","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","agile-planning",[1380,9,475],"agile",{"slug":1382,"featured":91,"template":679},"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":1388,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1389,"content":1395,"config":1400,"_id":1402,"_type":14,"title":1403,"_source":16,"_file":1404,"_stem":1405,"_extension":19},"/en-us/blog/dunelm-strengthens-business-by-enhancing-its-devsecops-culture",{"title":1390,"description":1391,"ogTitle":1390,"ogDescription":1391,"noIndex":6,"ogImage":1392,"ogUrl":1393,"ogSiteName":667,"ogType":668,"canonicalUrls":1393,"schema":1394},"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":1390,"description":1391,"authors":1396,"heroImage":1392,"date":1397,"body":1398,"category":953,"tags":1399},[737],"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/)._",[955,9,475,675],{"slug":1401,"featured":6,"template":679},"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":1407,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1408,"content":1414,"config":1419,"_id":1421,"_type":14,"title":1422,"_source":16,"_file":1423,"_stem":1424,"_extension":19},"/en-us/blog/efficient-devsecops-workflows-hands-on-python-gitlab-api-automation",{"ogTitle":1409,"schema":1410,"ogImage":1411,"ogDescription":1412,"ogSiteName":667,"noIndex":6,"ogType":668,"ogUrl":1413,"title":1409,"canonicalUrls":1413,"description":1412},"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      }","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659883/Blog/Hero%20Images/post-cover-image.jpg","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":1409,"description":1412,"authors":1415,"heroImage":1411,"date":1416,"body":1417,"category":890,"tags":1418},[1299],"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/2022/12/14/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/2021/02/18/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/2022/02/17/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/2021/04/21/devops-workflows-json-format-jq-ci-cd-lint/). The [GitLab CLI](/blog/2022/12/07/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}",[231,808,9,475],{"slug":1420,"featured":6,"template":679},"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":1426,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1427,"content":1433,"config":1440,"_id":1442,"_type":14,"title":1443,"_source":16,"_file":1444,"_stem":1445,"_extension":19},"/en-us/blog/efficient-devsecops-workflows-with-rules-for-conditional-pipelines",{"title":1428,"description":1429,"ogTitle":1428,"ogDescription":1429,"noIndex":6,"ogImage":1430,"ogUrl":1431,"ogSiteName":667,"ogType":668,"canonicalUrls":1431,"schema":1432},"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":1434,"description":1429,"authors":1435,"heroImage":1430,"date":1437,"body":1438,"category":890,"tags":1439},"How to create efficient DevSecOps workflows with rules for conditional CI/CD pipelines",[1436],"Abubakar Siddiq Ango","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",[808,806,807,9,475],{"slug":1441,"featured":6,"template":679},"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":1447,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1448,"content":1454,"config":1460,"_id":1462,"_type":14,"title":1463,"_source":16,"_file":1464,"_stem":1465,"_extension":19},"/en-us/blog/eliminate-risk-with-feature-flags-tutorial",{"title":1449,"description":1450,"ogTitle":1449,"ogDescription":1450,"noIndex":6,"ogImage":1451,"ogUrl":1452,"ogSiteName":667,"ogType":668,"canonicalUrls":1452,"schema":1453},"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":1449,"description":1450,"authors":1455,"heroImage":1451,"date":1457,"body":1458,"category":10,"tags":1459},[1456],"Cesar Saavedra","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",[109,700,9],{"slug":1461,"featured":6,"template":679},"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":1467,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1468,"content":1474,"config":1481,"_id":1483,"_type":14,"title":1484,"_source":16,"_file":1485,"_stem":1486,"_extension":19},"/en-us/blog/empowering-modelops-and-hpc-workloads-with-gpu-enabled-runners",{"title":1469,"description":1470,"ogTitle":1469,"ogDescription":1470,"noIndex":6,"ogImage":1471,"ogUrl":1472,"ogSiteName":667,"ogType":668,"canonicalUrls":1472,"schema":1473},"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":1475,"description":1470,"authors":1476,"heroImage":1471,"date":1478,"body":1479,"category":762,"tags":1480},"Empower ModelOps and HPC workloads with GPU-enabled runners integrated with CI/CD",[1477],"Gabriel Engel","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",[9,698,109,829,700],{"slug":1482,"featured":6,"template":679},"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":1488,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1489,"content":1492,"config":1498,"_id":1500,"_type":14,"title":1501,"_source":16,"_file":1502,"_stem":1503,"_extension":19},"/en-us/blog/enhance-application-quality-with-ai-powered-test-generation",{"noIndex":6,"title":1490,"description":1491},"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":1490,"description":1491,"authors":1493,"heroImage":1494,"date":1495,"body":1496,"category":762,"tags":1497},[1456],"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/2025/04/17/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/)",[698,829,1179,9,808,1065],{"featured":91,"template":679,"slug":1499},"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":1505,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1506,"content":1512,"config":1519,"_id":1521,"_type":14,"title":1522,"_source":16,"_file":1523,"_stem":1524,"_extension":19},"/en-us/blog/enhance-application-security-with-gitlab-hackerone",{"title":1507,"description":1508,"ogTitle":1507,"ogDescription":1508,"noIndex":6,"ogImage":1509,"ogUrl":1510,"ogSiteName":667,"ogType":668,"canonicalUrls":1510,"schema":1511},"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":1507,"description":1508,"authors":1513,"heroImage":1509,"date":1515,"body":1516,"category":675,"tags":1517},[1514],"Fernando Diaz","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",[675,808,231,282,475,9,1518],"bug bounty",{"slug":1520,"featured":6,"template":679},"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":1526,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1527,"content":1533,"config":1539,"_id":1541,"_type":14,"title":1542,"_source":16,"_file":1543,"_stem":1544,"_extension":19},"/en-us/blog/expanding-gitlab-for-startups-program",{"title":1528,"description":1529,"ogTitle":1528,"ogDescription":1529,"noIndex":6,"ogImage":1530,"ogUrl":1531,"ogSiteName":667,"ogType":668,"canonicalUrls":1531,"schema":1532},"Expanding GitLab for Startups program","Learn how startups can access the complete DevSecOps platform.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664087/Blog/Hero%20Images/tanukicover.jpg","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":1528,"description":1529,"authors":1534,"heroImage":1530,"date":1535,"body":1536,"category":975,"tags":1537},[972],"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",[9,1538,975],"startups",{"slug":1540,"featured":6,"template":679},"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":1546,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1547,"content":1552,"config":1558,"_id":1560,"_type":14,"title":1561,"_source":16,"_file":1562,"_stem":1563,"_extension":19},"/en-us/blog/explain-this-vulnerability",{"title":1548,"description":1549,"ogTitle":1548,"ogDescription":1549,"noIndex":6,"ogImage":1530,"ogUrl":1550,"ogSiteName":667,"ogType":668,"canonicalUrls":1550,"schema":1551},"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":1548,"description":1549,"authors":1553,"heroImage":1530,"date":1555,"body":1556,"category":762,"tags":1557},[1554],"Alana Bellucci","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",[975,700,9,698],{"slug":1559,"featured":6,"template":679},"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":1565,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1566,"content":1571,"config":1577,"_id":1579,"_type":14,"title":1580,"_source":16,"_file":1581,"_stem":1582,"_extension":19},"/en-us/blog/extending-code-suggestions",{"title":1567,"description":1568,"ogTitle":1567,"ogDescription":1568,"noIndex":6,"ogImage":820,"ogUrl":1569,"ogSiteName":667,"ogType":668,"canonicalUrls":1569,"schema":1570},"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":1567,"description":1568,"authors":1572,"heroImage":820,"date":1574,"body":1575,"category":762,"tags":1576},[1573],"Kai Armstrong","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",[9,829,700,698],{"slug":1578,"featured":6,"template":679},"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":1584,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1585,"content":1591,"config":1597,"_id":1599,"_type":14,"title":1600,"_source":16,"_file":1601,"_stem":1602,"_extension":19},"/en-us/blog/faq-gitlab-ci-cd-catalog",{"title":1586,"description":1587,"ogTitle":1586,"ogDescription":1587,"noIndex":6,"ogImage":1588,"ogUrl":1589,"ogSiteName":667,"ogType":668,"canonicalUrls":1589,"schema":1590},"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":1586,"description":1587,"authors":1592,"heroImage":1588,"date":1594,"body":1595,"category":890,"tags":1596},[1593,1102],"Itzik Gan Baruch","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",[109,9],{"slug":1598,"featured":91,"template":679},"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":1604,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1605,"content":1611,"config":1617,"_id":1619,"_type":14,"title":1620,"_source":16,"_file":1621,"_stem":1622,"_extension":19},"/en-us/blog/five-reasons-to-simplify-agile-planning-tool-configuration-gitlab",{"title":1606,"description":1607,"ogTitle":1606,"ogDescription":1607,"noIndex":6,"ogImage":1608,"ogUrl":1609,"ogSiteName":667,"ogType":668,"canonicalUrls":1609,"schema":1610},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749665084/Blog/Hero%20Images/agile.png","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":1606,"description":1607,"authors":1612,"heroImage":1608,"date":1614,"body":1615,"category":1378,"tags":1616},[1613],"Melissa Ushakov","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",[1380,475,9,829],{"slug":1618,"featured":6,"template":679},"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":1624,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1625,"content":1631,"config":1636,"_id":1638,"_type":14,"title":1639,"_source":16,"_file":1640,"_stem":1641,"_extension":19},"/en-us/blog/five-ways-to-streamline-cloud-adoption",{"title":1626,"description":1627,"ogTitle":1626,"ogDescription":1627,"noIndex":6,"ogImage":1628,"ogUrl":1629,"ogSiteName":667,"ogType":668,"canonicalUrls":1629,"schema":1630},"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":1626,"description":1627,"authors":1632,"heroImage":1628,"date":1633,"body":1634,"category":10,"tags":1635},[737],"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",[9,934,806,807],{"slug":1637,"featured":6,"template":679},"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":1643,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1644,"content":1650,"config":1656,"_id":1658,"_type":14,"title":1659,"_source":16,"_file":1660,"_stem":1661,"_extension":19},"/en-us/blog/getting-started-with-gitlab-application-security",{"title":1645,"description":1646,"ogTitle":1645,"ogDescription":1646,"noIndex":6,"ogImage":1647,"ogUrl":1648,"ogSiteName":667,"ogType":668,"canonicalUrls":1648,"schema":1649},"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":1645,"description":1646,"authors":1651,"heroImage":1647,"date":1653,"body":1654,"category":890,"tags":1655},[1652,717],"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",[9,806,807,675],{"slug":1657,"featured":6,"template":679},"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":1663,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1664,"content":1670,"config":1675,"_id":1677,"_type":14,"title":1678,"_source":16,"_file":1679,"_stem":1680,"_extension":19},"/en-us/blog/github-to-gitlab-migration-made-easy",{"title":1665,"description":1666,"ogTitle":1665,"ogDescription":1666,"noIndex":6,"ogImage":1667,"ogUrl":1668,"ogSiteName":667,"ogType":668,"canonicalUrls":1668,"schema":1669},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749668776/Blog/Hero%20Images/julia-craice-faCwTallTC0-unsplash.jpg","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":1665,"description":1666,"authors":1671,"heroImage":1667,"date":1672,"body":1673,"category":10,"tags":1674},[1514],"2023-07-11","\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",[109,808,9,475],{"slug":1676,"featured":6,"template":679},"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":1682,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1683,"content":1689,"config":1696,"_id":1698,"_type":14,"title":1699,"_source":16,"_file":1700,"_stem":1701,"_extension":19},"/en-us/blog/gitlab-advanced-sast-is-now-generally-available",{"title":1684,"description":1685,"ogTitle":1684,"ogDescription":1685,"noIndex":6,"ogImage":1686,"ogUrl":1687,"ogSiteName":667,"ogType":668,"canonicalUrls":1687,"schema":1688},"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":1684,"description":1685,"authors":1690,"heroImage":1686,"date":1693,"body":1694,"category":675,"tags":1695},[1691,1692],"Salman Ladha","Connor Gilbert","2024-09-19","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",[675,975,700,9,829],{"slug":1697,"featured":91,"template":679},"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":1703,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1704,"content":1710,"config":1716,"_id":1718,"_type":14,"title":1719,"_source":16,"_file":1720,"_stem":1721,"_extension":19},"/en-us/blog/gitlab-ai-assisted-features",{"title":1705,"description":1706,"ogTitle":1705,"ogDescription":1706,"noIndex":6,"ogImage":1707,"ogUrl":1708,"ogSiteName":667,"ogType":668,"canonicalUrls":1708,"schema":1709},"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":1705,"description":1706,"authors":1711,"heroImage":1707,"date":1713,"body":1714,"category":762,"tags":1715},[1712],"Sid Sijbrandij","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/)",[975,700,698,9],{"slug":1717,"featured":6,"template":679},"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":1723,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1724,"content":1730,"config":1736,"_id":1738,"_type":14,"title":1739,"_source":16,"_file":1740,"_stem":1741,"_extension":19},"/en-us/blog/gitlab-and-google-together-at-google-cloud-next-23",{"title":1725,"description":1726,"ogTitle":1725,"ogDescription":1726,"noIndex":6,"ogImage":1727,"ogUrl":1728,"ogSiteName":667,"ogType":668,"canonicalUrls":1728,"schema":1729},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749679290/Blog/Hero%20Images/gitlabgooglecloud.png","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":1725,"description":1726,"authors":1731,"heroImage":1727,"date":1733,"body":1734,"category":975,"tags":1735},[1732],"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",[975,675,1021,9],{"slug":1737,"featured":6,"template":679},"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":1743,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1744,"content":1750,"config":1756,"_id":1758,"_type":14,"title":1759,"_source":16,"_file":1760,"_stem":1761,"_extension":19},"/en-us/blog/gitlab-at-aws-re-invent-2023",{"title":1745,"description":1746,"ogTitle":1745,"ogDescription":1746,"noIndex":6,"ogImage":1747,"ogUrl":1748,"ogSiteName":667,"ogType":668,"canonicalUrls":1748,"schema":1749},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749664472/Blog/Hero%20Images/gitlabflatlogomap.png","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":1745,"description":1746,"authors":1751,"heroImage":1747,"date":1753,"body":1754,"category":10,"tags":1755},[1752],"Darwin Sanoy","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",[1065,9,475,282],{"slug":1757,"featured":91,"template":679},"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":1763,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1764,"content":1769,"config":1775,"_id":1777,"_type":14,"title":1778,"_source":16,"_file":1779,"_stem":1780,"_extension":19},"/en-us/blog/gitlab-chat-ai",{"title":1765,"description":1766,"ogTitle":1765,"ogDescription":1766,"noIndex":6,"ogImage":820,"ogUrl":1767,"ogSiteName":667,"ogType":668,"canonicalUrls":1767,"schema":1768},"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":1765,"description":1766,"authors":1770,"heroImage":820,"date":1772,"body":1773,"category":762,"tags":1774},[1771],"Sarah Waldner","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",[9,829,700,698],{"slug":1776,"featured":6,"template":679},"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":1782,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1783,"content":1786,"config":1793,"_id":1795,"_type":14,"title":1796,"_source":16,"_file":1797,"_stem":1798,"_extension":19},"/en-us/blog/gitlab-duo-agent-platform-what-is-next-for-intelligent-devsecops",{"noIndex":6,"title":1784,"description":1785},"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":1787,"title":1784,"description":1785,"authors":1788,"date":1790,"body":1791,"category":762,"tags":1792},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1750687578/esmflevxk5bf3eezjhwk.png",[1789],"Bill Staples","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/2025/05/29/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/)",[698,9,975,829],{"featured":91,"template":679,"slug":1794},"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":1800,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1801,"content":1807,"config":1812,"_id":1814,"_type":14,"title":1815,"_source":16,"_file":1816,"_stem":1817,"_extension":19},"/en-us/blog/gitlab-duo-chat-101-get-more-done-on-gitlab-with-our-ai-assistant",{"title":1802,"description":1803,"ogTitle":1802,"ogDescription":1803,"noIndex":6,"ogImage":1804,"ogUrl":1805,"ogSiteName":667,"ogType":668,"canonicalUrls":1805,"schema":1806},"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":1802,"description":1803,"authors":1808,"heroImage":1804,"date":1809,"body":1810,"category":762,"tags":1811},[1436],"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.",[698,475,9,808],{"slug":1813,"featured":91,"template":679},"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":1819,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1820,"content":1826,"config":1832,"_id":1834,"_type":14,"title":1835,"_source":16,"_file":1836,"_stem":1837,"_extension":19},"/en-us/blog/gitlab-duo-chat-beta",{"title":1821,"description":1822,"ogTitle":1821,"ogDescription":1822,"noIndex":6,"ogImage":1823,"ogUrl":1824,"ogSiteName":667,"ogType":668,"canonicalUrls":1824,"schema":1825},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749669095/Blog/Hero%20Images/gitlabduo.png","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":1821,"description":1822,"authors":1827,"heroImage":1823,"date":1829,"body":1830,"category":762,"tags":1831},[1828],"Torsten Linz","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",[698,9,975],{"slug":1833,"featured":6,"template":679},"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":1839,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1840,"content":1846,"config":1853,"_id":1855,"_type":14,"title":1856,"_source":16,"_file":1857,"_stem":1858,"_extension":19},"/en-us/blog/gitlab-duo-chat-get-to-know-productivity-boosting-ai-enhancements",{"title":1841,"description":1842,"ogTitle":1841,"ogDescription":1842,"noIndex":6,"ogImage":1843,"ogUrl":1844,"ogSiteName":667,"ogType":668,"canonicalUrls":1844,"schema":1845},"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":1841,"description":1842,"authors":1847,"heroImage":1843,"date":1850,"body":1851,"category":762,"tags":1852},[1848,1849],"Jannik Lehmann","David O'Regan","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).",[698,9,700,829],{"slug":1854,"featured":6,"template":679},"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":1860,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1861,"content":1866,"config":1872,"_id":1874,"_type":14,"title":1875,"_source":16,"_file":1876,"_stem":1877,"_extension":19},"/en-us/blog/gitlab-duo-code-suggestions-is-generally-available",{"title":1862,"description":1863,"ogTitle":1862,"ogDescription":1863,"noIndex":6,"ogImage":1823,"ogUrl":1864,"ogSiteName":667,"ogType":668,"canonicalUrls":1864,"schema":1865},"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":1862,"description":1863,"authors":1867,"heroImage":1823,"date":1869,"body":1870,"category":762,"tags":1871},[1868],"David DeSanto, Chief Product Officer, GitLab","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",[698,975,9],{"slug":1873,"featured":91,"template":679},"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":1879,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1880,"content":1886,"config":1890,"_id":1892,"_type":14,"title":1893,"_source":16,"_file":1894,"_stem":1895,"_extension":19},"/en-us/blog/gitlab-duo-code-suggestions-python",{"title":1881,"description":1882,"ogTitle":1881,"ogDescription":1882,"noIndex":6,"ogImage":1883,"ogUrl":1884,"ogSiteName":667,"ogType":668,"canonicalUrls":1884,"schema":1885},"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":1881,"description":1882,"authors":1887,"heroImage":1883,"date":1062,"body":1888,"category":762,"tags":1889},[1593],"\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",[975,700,698,9],{"slug":1891,"featured":6,"template":679},"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":1897,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1898,"content":1903,"config":1909,"_id":1911,"_type":14,"title":1912,"_source":16,"_file":1913,"_stem":1914,"_extension":19},"/en-us/blog/gitlab-duo-pro",{"title":1899,"description":1900,"ogTitle":1899,"ogDescription":1900,"noIndex":6,"ogImage":1823,"ogUrl":1901,"ogSiteName":667,"ogType":668,"canonicalUrls":1901,"schema":1902}," 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":1899,"description":1900,"authors":1904,"heroImage":1823,"date":1906,"body":1907,"category":762,"tags":1908},[1905,867],"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",[698,475,9],{"slug":1910,"featured":91,"template":679},"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":1916,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1917,"content":1922,"config":1927,"_id":1929,"_type":14,"title":1930,"_source":16,"_file":1931,"_stem":1932,"_extension":19},"/en-us/blog/gitlab-enterprise-agile-planning-add-on-for-all-roles",{"title":1918,"description":1919,"ogTitle":1918,"ogDescription":1919,"noIndex":6,"ogImage":1608,"ogUrl":1920,"ogSiteName":667,"ogType":668,"canonicalUrls":1920,"schema":1921},"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://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":1918,"description":1919,"authors":1923,"heroImage":1608,"date":1397,"body":1925,"category":1378,"tags":1926},[1924,1613],"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",[1380,9,475],{"slug":1928,"featured":91,"template":679},"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":1934,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1935,"content":1940,"config":1946,"_id":1948,"_type":14,"title":1949,"_source":16,"_file":1950,"_stem":1951,"_extension":19},"/en-us/blog/gitlab-flow-duo",{"title":1936,"description":1937,"ogTitle":1936,"ogDescription":1937,"noIndex":6,"ogImage":820,"ogUrl":1938,"ogSiteName":667,"ogType":668,"canonicalUrls":1938,"schema":1939},"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":1936,"description":1937,"authors":1941,"heroImage":820,"date":1942,"body":1943,"category":762,"tags":1944,"updatedDate":1945},[1456],"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",[109,698,9],"2024-06-18",{"slug":1947,"featured":6,"template":679},"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":1953,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1954,"content":1959,"config":1966,"_id":1968,"_type":14,"title":1969,"_source":16,"_file":1970,"_stem":1971,"_extension":19},"/en-us/blog/gitlab-global-devsecops-ai-report",{"title":1955,"description":1956,"ogTitle":1955,"ogDescription":1956,"noIndex":6,"ogImage":923,"ogUrl":1957,"ogSiteName":667,"ogType":668,"canonicalUrls":1957,"schema":1958},"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":1960,"description":1956,"authors":1961,"heroImage":923,"date":1963,"body":1964,"category":762,"tags":1965},"GitLab Global DevSecOps AI Report: Ushering in a new era of software development",[1962],"Ashley Kramer","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",[9,698,933],{"slug":1967,"featured":6,"template":679},"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":1973,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1974,"content":1979,"config":1984,"_id":1986,"_type":14,"title":1987,"_source":16,"_file":1988,"_stem":1989,"_extension":19},"/en-us/blog/gitlab-jetbrains-neovim-plugins",{"title":1975,"description":1976,"ogTitle":1975,"ogDescription":1976,"noIndex":6,"ogImage":820,"ogUrl":1977,"ogSiteName":667,"ogType":668,"canonicalUrls":1977,"schema":1978},"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":1975,"description":1976,"authors":1980,"heroImage":820,"date":1981,"body":1982,"category":762,"tags":1983},[1573],"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",[9,829,700,698],{"slug":1985,"featured":6,"template":679},"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":1991,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":1992,"content":1998,"config":2004,"_id":2006,"_type":14,"title":2007,"_source":16,"_file":2008,"_stem":2009,"_extension":19},"/en-us/blog/gitlab-named-a-leader-in-2024-gartner-magic-quadrant-for-ai-code-assistants",{"title":1993,"description":1994,"ogTitle":1993,"ogDescription":1994,"noIndex":6,"ogImage":1995,"ogUrl":1996,"ogSiteName":667,"ogType":668,"canonicalUrls":1996,"schema":1997},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749664458/Blog/Hero%20Images/Gartner_AI_Code_Assistants_Blog_Post_Cover_Image_1800x945.png","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":1993,"description":1994,"authors":1999,"heroImage":1995,"date":2000,"body":2001,"category":762,"tags":2002},[867],"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",[975,698,9,2003],"research",{"slug":2005,"featured":91,"template":679},"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":2011,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2012,"content":2018,"config":2024,"_id":2026,"_type":14,"title":2027,"_source":16,"_file":2028,"_stem":2029,"_extension":19},"/en-us/blog/gitlab-named-a-leader-in-the-2024-gartner-magic-quadrant-for-devops",{"title":2013,"description":2014,"ogTitle":2013,"ogDescription":2014,"noIndex":6,"ogImage":2015,"ogUrl":2016,"ogSiteName":667,"ogType":668,"canonicalUrls":2016,"schema":2017},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749662523/Blog/Hero%20Images/Gartner_DevOps_Blog_Post_Cover_Image_1800x945__2_.png","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":2019,"description":2014,"authors":2020,"heroImage":2015,"date":2021,"body":2022,"category":975,"tags":2023},"GitLab named a Leader in the 2024 Gartner Magic Quadrant for DevOps Platforms",[1962],"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.***",[975,2003,475,1280,9],{"slug":2025,"featured":91,"template":679},"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":2031,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2032,"content":2038,"config":2044,"_id":2046,"_type":14,"title":2047,"_source":16,"_file":2048,"_stem":2049,"_extension":19},"/en-us/blog/gitlab-package-roadmap-for-2024",{"title":2033,"description":2034,"ogTitle":2033,"ogDescription":2034,"noIndex":6,"ogImage":2035,"ogUrl":2036,"ogSiteName":667,"ogType":668,"canonicalUrls":2036,"schema":2037},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749669103/Blog/Hero%20Images/AdobeStock_243118595.jpg","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":2033,"description":2034,"authors":2039,"heroImage":2035,"date":2041,"body":2042,"category":829,"tags":2043},[2040],"Tim Rizzi","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._",[829,975,700,9],{"slug":2045,"featured":6,"template":679},"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":2051,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2052,"content":2058,"config":2066,"_id":2068,"_type":14,"title":2069,"_source":16,"_file":2070,"_stem":2071,"_extension":19},"/en-us/blog/gitlab-pages-features-review-apps-and-multiple-website-deployment",{"title":2053,"description":2054,"ogTitle":2053,"ogDescription":2054,"noIndex":6,"ogImage":2055,"ogUrl":2056,"ogSiteName":667,"ogType":668,"canonicalUrls":2056,"schema":2057},"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":2053,"description":2054,"authors":2059,"heroImage":2055,"date":2062,"body":2063,"category":829,"tags":2064,"updatedDate":2065},[2060,2061],"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",[1380,109,9,700,829,808],"2025-04-09",{"slug":2067,"featured":6,"template":679},"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":2073,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2074,"content":2080,"config":2087,"_id":2089,"_type":14,"title":2090,"_source":16,"_file":2091,"_stem":2092,"_extension":19},"/en-us/blog/gitlab-rezilion-integration-reduces-vulnerability-backlog-identifies-exploitable-risks-to-fix",{"title":2075,"description":2076,"ogTitle":2075,"ogDescription":2076,"noIndex":6,"ogImage":2077,"ogUrl":2078,"ogSiteName":667,"ogType":668,"canonicalUrls":2078,"schema":2079},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749668437/Blog/Hero%20Images/faster-cycle-times.jpg","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":2081,"description":2076,"authors":2082,"heroImage":2077,"date":2084,"body":2085,"category":675,"tags":2086},"How GitLab's integration with Rezilion reduces vulnerability backlog and identifies exploitable risks",[2083],"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",[675,9,231,975],{"slug":2088,"featured":6,"template":679},"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":2094,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2095,"content":2100,"config":2106,"_id":2108,"_type":14,"title":2109,"_source":16,"_file":2110,"_stem":2111,"_extension":19},"/en-us/blog/gitlab-security-hardening-documentation",{"title":2096,"description":2097,"ogTitle":2096,"ogDescription":2097,"noIndex":6,"ogImage":665,"ogUrl":2098,"ogSiteName":667,"ogType":668,"canonicalUrls":2098,"schema":2099},"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":2096,"description":2097,"authors":2101,"heroImage":665,"date":2103,"body":2104,"category":675,"tags":2105},[2102],"Mark Loveless","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",[675,934,9],{"slug":2107,"featured":6,"template":679},"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":2113,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2114,"content":2120,"config":2127,"_id":2129,"_type":14,"title":2130,"_source":16,"_file":2131,"_stem":2132,"_extension":19},"/en-us/blog/gitlab-supports-banks-in-navigating-regulatory-challenges",{"title":2115,"description":2116,"ogTitle":2115,"ogDescription":2116,"noIndex":6,"ogImage":2117,"ogUrl":2118,"ogSiteName":667,"ogType":668,"canonicalUrls":2118,"schema":2119},"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":2115,"description":2116,"authors":2121,"heroImage":2117,"date":2124,"body":2125,"category":675,"tags":2126},[2122,2123],"George Kichukov","Allie Holland","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/)",[551,9,475,675],{"slug":2128,"featured":6,"template":679},"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":2134,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2135,"content":2140,"config":2145,"_id":2147,"_type":14,"title":2148,"_source":16,"_file":2149,"_stem":2150,"_extension":19},"/en-us/blog/gitlab-survey-highlights-wins-challenges-as-orgs-adopt-devsecops",{"title":2136,"description":2137,"ogTitle":2136,"ogDescription":2137,"noIndex":6,"ogImage":923,"ogUrl":2138,"ogSiteName":667,"ogType":668,"canonicalUrls":2138,"schema":2139},"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":2136,"description":2137,"authors":2141,"heroImage":923,"date":2142,"body":2143,"category":10,"tags":2144},[1868],"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",[933,9,675,698],{"slug":2146,"featured":6,"template":679},"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":2152,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2153,"content":2156,"config":2164,"_id":2166,"_type":14,"title":2167,"_source":16,"_file":2168,"_stem":2169,"_extension":19},"/en-us/blog/gitlab-ultimate-for-ibm-z-modern-devsecops-for-mainframes",{"noIndex":6,"description":2154,"title":2155},"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":2155,"description":2154,"body":2157,"category":829,"tags":2158,"authors":2159,"heroImage":2162,"date":2163},"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,829,109,9],[2160,2161],"Mike Flouton","Andy Bradfield","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750440008/myqt5vcjlffh8sszw507.png","2025-06-23",{"featured":91,"template":679,"slug":2165},"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":2171,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2172,"content":2177,"config":2182,"_id":2184,"_type":14,"title":2185,"_source":16,"_file":2186,"_stem":2187,"_extension":19},"/en-us/blog/gitlab-uses-anthropic-for-smart-safe-ai-assisted-code-generation",{"title":2173,"description":2174,"ogTitle":2173,"ogDescription":2174,"noIndex":6,"ogImage":1823,"ogUrl":2175,"ogSiteName":667,"ogType":668,"canonicalUrls":2175,"schema":2176},"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":2173,"description":2174,"authors":2178,"heroImage":1823,"date":2041,"body":2180,"category":762,"tags":2181},[2179],"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!",[698,231,9,1280],{"slug":2183,"featured":91,"template":679},"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":2189,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2190,"content":2195,"config":2200,"_id":2202,"_type":14,"title":2203,"_source":16,"_file":2204,"_stem":2205,"_extension":19},"/en-us/blog/gitlab-visual-studio-extension",{"title":2191,"description":2192,"ogTitle":2191,"ogDescription":2192,"noIndex":6,"ogImage":820,"ogUrl":2193,"ogSiteName":667,"ogType":668,"canonicalUrls":2193,"schema":2194},"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":2191,"description":2192,"authors":2196,"heroImage":820,"date":2197,"body":2198,"category":762,"tags":2199},[1573],"2023-06-29","\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",[9,829,700,698],{"slug":2201,"featured":6,"template":679},"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":2207,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2208,"content":2213,"config":2218,"_id":2220,"_type":14,"title":2221,"_source":16,"_file":2222,"_stem":2223,"_extension":19},"/en-us/blog/gitlabs-maven-dependency-proxy-is-available-in-beta",{"title":2209,"description":2210,"ogTitle":2209,"ogDescription":2210,"noIndex":6,"ogImage":923,"ogUrl":2211,"ogSiteName":667,"ogType":668,"canonicalUrls":2211,"schema":2212},"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://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":2209,"description":2210,"authors":2214,"heroImage":923,"date":2215,"body":2216,"category":975,"tags":2217},[2040],"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",[975,109,1020,9],{"slug":2219,"featured":91,"template":679},"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":2225,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2226,"content":2232,"config":2239,"_id":2241,"_type":14,"title":2242,"_source":16,"_file":2243,"_stem":2244,"_extension":19},"/en-us/blog/happy-birthday-secure-by-design",{"title":2227,"description":2228,"ogTitle":2227,"ogDescription":2228,"noIndex":6,"ogImage":2229,"ogUrl":2230,"ogSiteName":667,"ogType":668,"canonicalUrls":2230,"schema":2231},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749664530/Blog/Hero%20Images/AdobeStock_282096522.jpg","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":2227,"description":2228,"authors":2233,"heroImage":2229,"date":2235,"body":2236,"category":675,"tags":2237},[2234],"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/).",[675,475,9,2238,184],"zero trust",{"slug":2240,"featured":91,"template":679},"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":2246,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2247,"content":2253,"config":2258,"_id":2260,"_type":14,"title":2261,"_source":16,"_file":2262,"_stem":2263,"_extension":19},"/en-us/blog/hosted-runners-for-gitlab-dedicated-now-in-limited-availability",{"title":2248,"description":2249,"ogTitle":2248,"ogDescription":2249,"noIndex":6,"ogImage":2250,"ogUrl":2251,"ogSiteName":667,"ogType":668,"canonicalUrls":2251,"schema":2252},"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":2248,"description":2249,"authors":2254,"heroImage":2250,"date":2255,"body":2256,"category":829,"tags":2257},[1477],"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",[9,475,700,975,109,184],{"slug":2259,"featured":6,"template":679},"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":2265,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2266,"content":2272,"config":2277,"_id":2279,"_type":14,"title":2280,"_source":16,"_file":2281,"_stem":2282,"_extension":19},"/en-us/blog/how-carrefour-and-thales-are-evolving-their-ci-cd-platforms",{"title":2267,"description":2268,"ogTitle":2267,"ogDescription":2268,"noIndex":6,"ogImage":2269,"ogUrl":2270,"ogSiteName":667,"ogType":668,"canonicalUrls":2270,"schema":2271},"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":2267,"description":2268,"authors":2273,"heroImage":2269,"date":2274,"body":2275,"category":953,"tags":2276},[928],"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",[109,955,9],{"slug":2278,"featured":91,"template":679},"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":2284,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2285,"content":2290,"config":2296,"_id":2298,"_type":14,"title":2299,"_source":16,"_file":2300,"_stem":2301,"_extension":19},"/en-us/blog/how-cube-uses-gitlab-to-increase-efficiency-and-productivity",{"title":2286,"description":2287,"ogTitle":2286,"ogDescription":2287,"noIndex":6,"ogImage":2077,"ogUrl":2288,"ogSiteName":667,"ogType":668,"canonicalUrls":2288,"schema":2289},"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://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":2286,"description":2287,"authors":2291,"heroImage":2077,"date":2293,"body":2294,"category":953,"tags":2295},[2292],"GitLab","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.",[9,955,109],{"slug":2297,"featured":6,"template":679},"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":2303,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2304,"content":2310,"config":2315,"_id":2317,"_type":14,"title":2318,"_source":16,"_file":2319,"_stem":2320,"_extension":19},"/en-us/blog/how-devsecops-drives-business-success",{"title":2305,"description":2306,"ogTitle":2305,"ogDescription":2306,"noIndex":6,"ogImage":2307,"ogUrl":2308,"ogSiteName":667,"ogType":668,"canonicalUrls":2308,"schema":2309},"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":2305,"description":2306,"authors":2311,"heroImage":2307,"date":2312,"body":2313,"category":10,"tags":2314},[737],"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",[475,742,9],{"slug":2316,"featured":6,"template":679},"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":2322,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2323,"content":2329,"config":2334,"_id":2336,"_type":14,"title":2337,"_source":16,"_file":2338,"_stem":2339,"_extension":19},"/en-us/blog/how-gitlab-duo-helps-secure-and-thoroughly-test-ai-generated-code",{"title":2324,"description":2325,"ogTitle":2324,"ogDescription":2325,"noIndex":6,"ogImage":2326,"ogUrl":2327,"ogSiteName":667,"ogType":668,"canonicalUrls":2327,"schema":2328},"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":2324,"description":2325,"authors":2330,"heroImage":2326,"date":2331,"body":2332,"category":762,"tags":2333},[1849],"2024-05-30","___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",[698,9,808,675],{"slug":2335,"featured":6,"template":679},"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":2341,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2342,"content":2347,"config":2353,"_id":2355,"_type":14,"title":2356,"_source":16,"_file":2357,"_stem":2358,"_extension":19},"/en-us/blog/how-gitlab-measures-red-team-impact-the-adoption-rate-metric",{"title":2343,"description":2344,"ogTitle":2343,"ogDescription":2344,"noIndex":6,"ogImage":903,"ogUrl":2345,"ogSiteName":667,"ogType":668,"canonicalUrls":2345,"schema":2346},"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":2343,"description":2344,"authors":2348,"heroImage":903,"date":2350,"body":2351,"category":675,"tags":2352},[2349],"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/)",[675,9,1019],{"slug":2354,"featured":6,"template":679},"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":2360,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2361,"content":2366,"config":2372,"_id":2374,"_type":14,"title":2375,"_source":16,"_file":2376,"_stem":2377,"_extension":19},"/en-us/blog/how-gitlab-supports-the-fedramp-authorization-journey",{"title":2362,"description":2363,"ogTitle":2362,"ogDescription":2363,"noIndex":6,"ogImage":1252,"ogUrl":2364,"ogSiteName":667,"ogType":668,"canonicalUrls":2364,"schema":2365},"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":2362,"description":2363,"authors":2367,"heroImage":1252,"date":2369,"body":2370,"category":675,"tags":2371},[2368],"Christian Nnachi","2024-08-07","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/).",[808,184,9],{"slug":2373,"featured":91,"template":679},"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":2379,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2380,"content":2386,"config":2391,"_id":2393,"_type":14,"title":2394,"_source":16,"_file":2395,"_stem":2396,"_extension":19},"/en-us/blog/how-to-gitlab-single-sign-on-with-saml-scim-and-azures-entra-id",{"title":2381,"description":2382,"ogTitle":2381,"ogDescription":2382,"noIndex":6,"ogImage":2383,"ogUrl":2384,"ogSiteName":667,"ogType":668,"canonicalUrls":2384,"schema":2385},"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":2381,"description":2382,"authors":2387,"heroImage":2383,"date":2255,"body":2389,"category":675,"tags":2390},[2388],"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/)",[808,675,475,9,1240],{"slug":2392,"featured":6,"template":679},"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":2398,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2399,"content":2405,"config":2410,"_id":2412,"_type":14,"title":2413,"_source":16,"_file":2414,"_stem":2415,"_extension":19},"/en-us/blog/how-to-harden-your-self-managed-gitlab-instance",{"title":2400,"description":2401,"ogTitle":2400,"ogDescription":2401,"noIndex":6,"ogImage":2402,"ogUrl":2403,"ogSiteName":667,"ogType":668,"canonicalUrls":2403,"schema":2404},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749664923/Blog/Hero%20Images/security-checklist.png","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":2400,"description":2401,"authors":2406,"heroImage":2402,"date":2407,"body":2408,"category":890,"tags":2409},[759],"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",[675,808,9],{"slug":2411,"featured":6,"template":679},"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":2417,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2418,"content":2423,"config":2428,"_id":2430,"_type":14,"title":2431,"_source":16,"_file":2432,"_stem":2433,"_extension":19},"/en-us/blog/how-to-successfully-deliver-your-software-development-roadmap",{"title":2419,"description":2420,"ogTitle":2419,"ogDescription":2420,"noIndex":6,"ogImage":2035,"ogUrl":2421,"ogSiteName":667,"ogType":668,"canonicalUrls":2421,"schema":2422},"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://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":2419,"description":2420,"authors":2424,"heroImage":2035,"date":2425,"body":2426,"category":10,"tags":2427},[1868],"2024-04-04","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",[698,9,475,675],{"slug":2429,"featured":91,"template":679},"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":2435,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2436,"content":2442,"config":2449,"_id":2451,"_type":14,"title":2452,"_source":16,"_file":2453,"_stem":2454,"_extension":19},"/en-us/blog/how-to-tailor-gitlab-access-with-custom-roles",{"title":2437,"description":2438,"ogTitle":2437,"ogDescription":2438,"noIndex":6,"ogImage":2439,"ogUrl":2440,"ogSiteName":667,"ogType":668,"canonicalUrls":2440,"schema":2441},"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":2437,"description":2438,"authors":2443,"heroImage":2439,"date":2446,"body":2447,"category":10,"tags":2448},[2444,2445],"Joe Randazzo","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",[829,675,9,700],{"slug":2450,"featured":91,"template":679},"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":2456,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2457,"content":2463,"config":2469,"_id":2471,"_type":14,"title":2472,"_source":16,"_file":2473,"_stem":2474,"_extension":19},"/en-us/blog/how-we-designed-the-gitlab-reference-architectures",{"title":2458,"description":2459,"ogTitle":2458,"ogDescription":2459,"noIndex":6,"ogImage":2460,"ogUrl":2461,"ogSiteName":667,"ogType":668,"canonicalUrls":2461,"schema":2462},"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":2458,"description":2459,"authors":2464,"heroImage":2460,"date":2466,"body":2467,"category":890,"tags":2468},[2465],"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",[806,9,1020,1019,955],{"slug":2470,"featured":91,"template":679},"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":2476,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2477,"content":2482,"config":2487,"_id":2489,"_type":14,"title":2490,"_source":16,"_file":2491,"_stem":2492,"_extension":19},"/en-us/blog/improve-ai-security-in-gitlab-with-composite-identities",{"title":2478,"description":2479,"ogTitle":2478,"ogDescription":2479,"noIndex":6,"ogImage":754,"ogUrl":2480,"ogSiteName":667,"ogType":668,"canonicalUrls":2480,"schema":2481},"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://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":2478,"description":2479,"authors":2483,"heroImage":754,"date":909,"body":2485,"category":675,"tags":2486},[2484],"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).",[698,9,675],{"slug":2488,"featured":6,"template":679},"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":2494,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2495,"content":2501,"config":2506,"_id":2508,"_type":14,"title":2509,"_source":16,"_file":2510,"_stem":2511,"_extension":19},"/en-us/blog/improve-security-auditing-with-gitlab-operational-container-scanning",{"title":2496,"description":2497,"ogTitle":2496,"ogDescription":2497,"noIndex":6,"ogImage":2498,"ogUrl":2499,"ogSiteName":667,"ogType":668,"canonicalUrls":2499,"schema":2500},"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":2496,"description":2497,"authors":2502,"heroImage":2498,"date":909,"body":2504,"category":675,"tags":2505},[2503],"Daniel Helfand","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/).",[700,9,808,675,829],{"slug":2507,"featured":6,"template":679},"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":2513,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2514,"content":2520,"config":2526,"_id":2528,"_type":14,"title":2529,"_source":16,"_file":2530,"_stem":2531,"_extension":19},"/en-us/blog/inside-dora-performers-score-in-gitlab-value-streams-dashboard",{"title":2515,"description":2516,"ogTitle":2515,"ogDescription":2516,"noIndex":6,"ogImage":2517,"ogUrl":2518,"ogSiteName":667,"ogType":668,"canonicalUrls":2518,"schema":2519},"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":2515,"description":2516,"authors":2521,"heroImage":2517,"date":2523,"body":2524,"category":10,"tags":2525},[2522],"Haim Snir","2024-01-18","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",[1280,9,475,829,1020],{"slug":2527,"featured":6,"template":679},"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":2533,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2534,"content":2540,"config":2545,"_id":2547,"_type":14,"title":2548,"_source":16,"_file":2549,"_stem":2550,"_extension":19},"/en-us/blog/interactive-take-a-guided-tour-of-the-devsecops-workflow",{"title":2535,"description":2536,"ogTitle":2535,"ogDescription":2536,"noIndex":6,"ogImage":2537,"ogUrl":2538,"ogSiteName":667,"ogType":668,"canonicalUrls":2538,"schema":2539},"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":2535,"description":2536,"authors":2541,"heroImage":2537,"date":2542,"body":2543,"category":10,"tags":2544},[1593],"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",[9,997,109],{"slug":2546,"featured":91,"template":679},"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":2552,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2553,"content":2559,"config":2565,"_id":2567,"_type":14,"title":2568,"_source":16,"_file":2569,"_stem":2570,"_extension":19},"/en-us/blog/introducing-gitlabs-open-source-security-center",{"title":2554,"description":2555,"ogTitle":2554,"ogDescription":2555,"noIndex":6,"ogImage":2556,"ogUrl":2557,"ogSiteName":667,"ogType":668,"canonicalUrls":2557,"schema":2558},"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":2554,"description":2555,"authors":2560,"heroImage":2556,"date":2562,"body":2563,"category":675,"tags":2564},[1691,2561],"Joseph Longo","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/)",[675,975,784,9,700],{"slug":2566,"featured":91,"template":679},"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":2572,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2573,"content":2579,"config":2585,"_id":2587,"_type":14,"title":2588,"_source":16,"_file":2589,"_stem":2590,"_extension":19},"/en-us/blog/introducing-the-source-insights-for-the-future-of-software-development",{"title":2574,"description":2575,"ogTitle":2574,"ogDescription":2575,"noIndex":6,"ogImage":2576,"ogUrl":2577,"ogSiteName":667,"ogType":668,"canonicalUrls":2577,"schema":2578},"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":2574,"description":2575,"authors":2580,"heroImage":2576,"date":2582,"body":2583,"category":975,"tags":2584},[2581],"Chandler Gibbons","2024-10-29","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-and-infrastructure/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.",[698,675,975,9],{"slug":2586,"featured":91,"template":679},"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":2592,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2593,"content":2598,"config":2603,"_id":2605,"_type":14,"title":2606,"_source":16,"_file":2607,"_stem":2608,"_extension":19},"/en-us/blog/jenkins-gitlab-ultimate-guide-to-modernizing-cicd-environment",{"title":2594,"description":2595,"ogTitle":2594,"ogDescription":2595,"noIndex":6,"ogImage":946,"ogUrl":2596,"ogSiteName":667,"ogType":668,"canonicalUrls":2596,"schema":2597},"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":2594,"description":2595,"authors":2599,"heroImage":946,"date":2600,"body":2601,"category":10,"tags":2602},[1593],"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",[808,277,698,231,9,1280],{"slug":2604,"featured":6,"template":679},"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":2610,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2611,"content":2617,"config":2622,"_id":2624,"_type":14,"title":2625,"_source":16,"_file":2626,"_stem":2627,"_extension":19},"/en-us/blog/jenkins-to-gitlab-migration-made-easy",{"title":2612,"description":2613,"ogTitle":2612,"ogDescription":2613,"noIndex":6,"ogImage":2614,"ogUrl":2615,"ogSiteName":667,"ogType":668,"canonicalUrls":2615,"schema":2616},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749663019/Blog/Hero%20Images/AdobeStock_519147119.jpg","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":2612,"description":2613,"authors":2618,"heroImage":2614,"date":2619,"body":2620,"category":10,"tags":2621},[1514],"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",[109,9],{"slug":2623,"featured":91,"template":679},"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":2629,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2630,"content":2636,"config":2641,"_id":2643,"_type":14,"title":2644,"_source":16,"_file":2645,"_stem":2646,"_extension":19},"/en-us/blog/keeping-your-development-dry",{"title":2631,"description":2632,"ogTitle":2631,"ogDescription":2632,"noIndex":6,"ogImage":2633,"ogUrl":2634,"ogSiteName":667,"ogType":668,"canonicalUrls":2634,"schema":2635},"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":2631,"description":2632,"authors":2637,"heroImage":2633,"date":2638,"body":2639,"category":890,"tags":2640},[802,2444],"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",[806,807,1280,9],{"slug":2642,"featured":6,"template":679},"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":2648,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2649,"content":2655,"config":2660,"_id":2662,"_type":14,"title":2663,"_source":16,"_file":2664,"_stem":2665,"_extension":19},"/en-us/blog/kingfisher-transforming-the-developer-experience-with-gitlab",{"title":2650,"description":2651,"ogTitle":2650,"ogDescription":2651,"noIndex":6,"ogImage":2652,"ogUrl":2653,"ogSiteName":667,"ogType":668,"canonicalUrls":2653,"schema":2654},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749659756/Blog/Hero%20Images/REFERENCE_-_display_preview_for_blog_images.png","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":2650,"description":2651,"authors":2656,"heroImage":2652,"date":2657,"body":2658,"category":953,"tags":2659},[737],"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",[955,475,9,997],{"slug":2661,"featured":91,"template":679},"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":2667,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2668,"content":2673,"config":2678,"_id":2680,"_type":14,"title":2681,"_source":16,"_file":2682,"_stem":2683,"_extension":19},"/en-us/blog/last-year-we-signed-the-secure-by-design-pledge-heres-our-progress",{"title":2669,"description":2670,"ogTitle":2669,"ogDescription":2670,"noIndex":6,"ogImage":1252,"ogUrl":2671,"ogSiteName":667,"ogType":668,"canonicalUrls":2671,"schema":2672},"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://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":2669,"description":2670,"authors":2674,"heroImage":1252,"date":2675,"body":2676,"category":675,"tags":2677},[2561],"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/)",[9,475,675,184],{"slug":2679,"featured":91,"template":679},"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":2685,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2686,"content":2692,"config":2697,"_id":2699,"_type":14,"title":2700,"_source":16,"_file":2701,"_stem":2702,"_extension":19},"/en-us/blog/learn-advanced-rust-programming-with-a-little-help-from-ai-code-suggestions",{"title":2687,"description":2688,"ogTitle":2687,"ogDescription":2688,"noIndex":6,"ogImage":2689,"ogUrl":2690,"ogSiteName":667,"ogType":668,"canonicalUrls":2690,"schema":2691},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749662439/Blog/Hero%20Images/codewithheart.png","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":2687,"description":2688,"authors":2693,"heroImage":2689,"date":2694,"body":2695,"category":762,"tags":2696},[1299],"2023-10-12","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",[9,742,808,997,698],{"slug":2698,"featured":6,"template":679},"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":2704,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2705,"content":2711,"config":2716,"_id":2718,"_type":14,"title":2719,"_source":16,"_file":2720,"_stem":2721,"_extension":19},"/en-us/blog/learning-rust-with-a-little-help-from-ai-code-suggestions-getting-started",{"title":2706,"description":2707,"ogTitle":2706,"ogDescription":2707,"noIndex":6,"ogImage":2708,"ogUrl":2709,"ogSiteName":667,"ogType":668,"canonicalUrls":2709,"schema":2710},"Learning Rust with a little help from AI","Use this guided tutorial, along with GitLab Duo Code Suggestions, to learn a new programming language.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663918/Blog/Hero%20Images/aipower.jpg","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":2706,"description":2707,"authors":2712,"heroImage":2708,"date":2713,"body":2714,"category":762,"tags":2715},[1299],"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",[9,742,808,997,698],{"slug":2717,"featured":6,"template":679},"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":2723,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2724,"content":2730,"config":2736,"_id":2738,"_type":14,"title":2739,"_source":16,"_file":2740,"_stem":2741,"_extension":19},"/en-us/blog/machine-learning-and-devsecops",{"title":2725,"description":2726,"ogTitle":2725,"ogDescription":2726,"noIndex":6,"ogImage":2727,"ogUrl":2728,"ogSiteName":667,"ogType":668,"canonicalUrls":2728,"schema":2729},"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":2725,"description":2726,"authors":2731,"heroImage":2727,"date":2733,"body":2734,"category":10,"tags":2735},[2732],"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",[231,698,9],{"slug":2737,"featured":6,"template":679},"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":2743,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2744,"content":2750,"config":2756,"_id":2758,"_type":14,"title":2759,"_source":16,"_file":2760,"_stem":2761,"_extension":19},"/en-us/blog/managing-gitlab-resources-with-pulumi",{"title":2745,"description":2746,"ogTitle":2745,"ogDescription":2746,"noIndex":6,"ogImage":2747,"ogUrl":2748,"ogSiteName":667,"ogType":668,"canonicalUrls":2748,"schema":2749},"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":2745,"description":2746,"authors":2751,"heroImage":2747,"date":2753,"body":2754,"category":10,"tags":2755},[2752],"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.",[109,9,282,231],{"slug":2757,"featured":6,"template":679},"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":2763,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2764,"content":2770,"config":2776,"_id":2778,"_type":14,"title":2779,"_source":16,"_file":2780,"_stem":2781,"_extension":19},"/en-us/blog/managing-multiple-environments-with-terraform-and-gitlab-ci",{"title":2765,"description":2766,"ogTitle":2765,"ogDescription":2766,"noIndex":6,"ogImage":2767,"ogUrl":2768,"ogSiteName":667,"ogType":668,"canonicalUrls":2768,"schema":2769},"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":2765,"description":2766,"authors":2771,"heroImage":2767,"date":2773,"body":2774,"category":675,"tags":2775},[2772,802],"Sophia Manicor","2023-06-14","\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",[1280,806,9,675],{"slug":2777,"featured":6,"template":679},"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":2783,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2784,"content":2790,"config":2796,"_id":2798,"_type":14,"title":2799,"_source":16,"_file":2800,"_stem":2801,"_extension":19},"/en-us/blog/measuring-ai-effectiveness-beyond-developer-productivity-metrics",{"title":2785,"description":2786,"ogTitle":2785,"ogDescription":2786,"noIndex":6,"ogImage":2787,"ogUrl":2788,"ogSiteName":667,"ogType":668,"canonicalUrls":2788,"schema":2789},"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":2785,"description":2786,"authors":2791,"heroImage":2787,"date":2793,"body":2794,"category":762,"tags":2795},[2792],"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._",[698,475,9,829],{"slug":2797,"featured":91,"template":679},"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":2803,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2804,"content":2810,"config":2814,"_id":2816,"_type":14,"title":2817,"_source":16,"_file":2818,"_stem":2819,"_extension":19},"/en-us/blog/medium-gitlab-saas-runners-on-linux-now-available-to-all-tiers",{"title":2805,"description":2806,"ogTitle":2805,"ogDescription":2806,"noIndex":6,"ogImage":2807,"ogUrl":2808,"ogSiteName":667,"ogType":668,"canonicalUrls":2808,"schema":2809},"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":2805,"description":2806,"authors":2811,"heroImage":2807,"date":2103,"body":2812,"category":975,"tags":2813},[1477],"\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",[109,9,975],{"slug":2815,"featured":6,"template":679},"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":2821,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2822,"content":2828,"config":2833,"_id":2835,"_type":14,"title":2836,"_source":16,"_file":2837,"_stem":2838,"_extension":19},"/en-us/blog/meet-gitlab-duo-the-suite-of-ai-capabilities",{"title":2823,"description":2824,"ogTitle":2823,"ogDescription":2824,"noIndex":6,"ogImage":2825,"ogUrl":2826,"ogSiteName":667,"ogType":668,"canonicalUrls":2826,"schema":2827},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749679194/Blog/Hero%20Images/duo-blog-post.png","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":2823,"description":2824,"authors":2829,"heroImage":2825,"date":2830,"body":2831,"category":762,"tags":2832},[1868],"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",[975,700,698,9],{"slug":2834,"featured":6,"template":679},"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":2840,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2841,"content":2847,"config":2852,"_id":2854,"_type":14,"title":2855,"_source":16,"_file":2856,"_stem":2857,"_extension":19},"/en-us/blog/meet-gitlab-duo-workflow-the-future-of-ai-driven-development",{"title":2842,"description":2843,"ogTitle":2842,"ogDescription":2843,"noIndex":6,"ogImage":2844,"ogUrl":2845,"ogSiteName":667,"ogType":668,"canonicalUrls":2845,"schema":2846},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749658912/Blog/Hero%20Images/blog-image-template-1800x945__20_.png","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":2842,"description":2843,"authors":2848,"heroImage":2844,"date":2849,"body":2850,"category":762,"tags":2851},[1868],"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).",[698,475,9,975,997],{"slug":2853,"featured":91,"template":679},"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":2859,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2860,"content":2866,"config":2871,"_id":2873,"_type":14,"title":2874,"_source":16,"_file":2875,"_stem":2876,"_extension":19},"/en-us/blog/meet-regulatory-standards-with-gitlab",{"title":2861,"description":2862,"ogTitle":2861,"ogDescription":2862,"noIndex":6,"ogImage":2863,"ogUrl":2864,"ogSiteName":667,"ogType":668,"canonicalUrls":2864,"schema":2865},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1750098739/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_282096522_securitycompliance.jpeg_1750098739024.jpg","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":2861,"description":2862,"authors":2867,"heroImage":2863,"date":2868,"body":2869,"category":675,"tags":2870,"updatedDate":2000},[1436],"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/)",[9,475,675,184],{"slug":2872,"featured":6,"template":679},"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":2878,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2879,"content":2885,"config":2890,"_id":2892,"_type":14,"title":2893,"_source":16,"_file":2894,"_stem":2895,"_extension":19},"/en-us/blog/memory-safe-vs-unsafe",{"title":2880,"description":2881,"ogTitle":2880,"ogDescription":2881,"noIndex":6,"ogImage":2882,"ogUrl":2883,"ogSiteName":667,"ogType":668,"canonicalUrls":2883,"schema":2884},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749672878/Blog/Hero%20Images/securityscreen.jpg","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":2880,"description":2881,"authors":2886,"heroImage":2882,"date":2887,"body":2888,"category":675,"tags":2889},[1514],"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)_",[675,9,808],{"slug":2891,"featured":6,"template":679},"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":2897,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2898,"content":2903,"config":2908,"_id":2910,"_type":14,"title":2911,"_source":16,"_file":2912,"_stem":2913,"_extension":19},"/en-us/blog/merge-request-suggest-a-test",{"title":2899,"description":2900,"ogTitle":2899,"ogDescription":2900,"noIndex":6,"ogImage":1471,"ogUrl":2901,"ogSiteName":667,"ogType":668,"canonicalUrls":2901,"schema":2902},"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":2899,"description":2900,"authors":2904,"heroImage":1471,"date":2905,"body":2906,"category":762,"tags":2907},[1573],"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",[9,829,700,698],{"slug":2909,"featured":6,"template":679},"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":2915,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2916,"content":2921,"config":2926,"_id":2928,"_type":14,"title":2929,"_source":16,"_file":2930,"_stem":2931,"_extension":19},"/en-us/blog/migrating-from-bamboo-to-gitlab-cicd",{"title":2917,"description":2918,"ogTitle":2917,"ogDescription":2918,"noIndex":6,"ogImage":861,"ogUrl":2919,"ogSiteName":667,"ogType":668,"canonicalUrls":2919,"schema":2920},"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":2917,"description":2918,"authors":2922,"heroImage":861,"date":2923,"body":2924,"category":10,"tags":2925},[1436],"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",[9,475],{"slug":2927,"featured":6,"template":679},"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":2933,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2934,"content":2939,"config":2945,"_id":2947,"_type":14,"title":2948,"_source":16,"_file":2949,"_stem":2950,"_extension":19},"/en-us/blog/modern-software-development-problems-require-modern-ai-powered-devsecops",{"title":2935,"description":2936,"ogTitle":2935,"ogDescription":2936,"noIndex":6,"ogImage":820,"ogUrl":2937,"ogSiteName":667,"ogType":668,"canonicalUrls":2937,"schema":2938},"Modern software development problems require modern AI-powered DevSecOps","Learn how applying AI can help solve common development challenges.","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":2935,"description":2936,"authors":2940,"heroImage":820,"date":2942,"body":2943,"category":762,"tags":2944},[2941],"William Arias","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",[9,475,698],{"slug":2946,"featured":6,"template":679},"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":2952,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2953,"content":2959,"config":2967,"_id":2969,"_type":14,"title":2970,"_source":16,"_file":2971,"_stem":2972,"_extension":19},"/en-us/blog/navigate-application-architecture-drift-and-organizational-alignment",{"title":2954,"description":2955,"ogTitle":2954,"ogDescription":2955,"noIndex":6,"ogImage":2956,"ogUrl":2957,"ogSiteName":667,"ogType":668,"canonicalUrls":2957,"schema":2958},"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":2954,"description":2955,"authors":2960,"heroImage":2956,"date":2963,"body":2964,"category":890,"tags":2965},[2961,2962],"Stephen Walters","Lee Faus","2024-09-18","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",[9,2966],"design",{"slug":2968,"featured":91,"template":679},"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":2974,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2975,"content":2980,"config":2986,"_id":2988,"_type":14,"title":2989,"_source":16,"_file":2990,"_stem":2991,"_extension":19},"/en-us/blog/new-cis-gitlab-benchmark-scanner-boosts-security-and-compliance",{"title":2976,"description":2977,"ogTitle":2976,"ogDescription":2977,"noIndex":6,"ogImage":2229,"ogUrl":2978,"ogSiteName":667,"ogType":668,"canonicalUrls":2978,"schema":2979},"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://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":2976,"description":2977,"authors":2981,"heroImage":2229,"date":2582,"body":2984,"category":675,"tags":2985},[908,2982,2983],"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",[675,700,9],{"slug":2987,"featured":6,"template":679},"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":2993,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":2994,"content":2999,"config":3005,"_id":3007,"_type":14,"title":3008,"_source":16,"_file":3009,"_stem":3010,"_extension":19},"/en-us/blog/new-report-on-ai-assisted-tools-points-to-rising-stakes-for-devsecops",{"title":2995,"description":2996,"ogTitle":2995,"ogDescription":2996,"noIndex":6,"ogImage":2708,"ogUrl":2997,"ogSiteName":667,"ogType":668,"canonicalUrls":2997,"schema":2998},"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":2995,"description":2996,"authors":3000,"heroImage":2708,"date":3002,"body":3003,"category":762,"tags":3004},[3001],"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",[698,9,975],{"slug":3006,"featured":91,"template":679},"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":3012,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3013,"content":3018,"config":3023,"_id":3025,"_type":14,"title":3026,"_source":16,"_file":3027,"_stem":3028,"_extension":19},"/en-us/blog/oidc",{"title":3014,"description":3015,"ogTitle":3014,"ogDescription":3015,"noIndex":6,"ogImage":775,"ogUrl":3016,"ogSiteName":667,"ogType":668,"canonicalUrls":3016,"schema":3017},"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://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":3014,"description":3015,"authors":3019,"heroImage":775,"date":3020,"body":3021,"category":10,"tags":3022},[1102],"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",[808,9,806,807],{"slug":3024,"featured":6,"template":679},"oidc","content:en-us:blog:oidc.yml","Oidc","en-us/blog/oidc.yml","en-us/blog/oidc",{"_path":3030,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3031,"content":3037,"config":3042,"_id":3044,"_type":14,"title":3045,"_source":16,"_file":3046,"_stem":3047,"_extension":19},"/en-us/blog/one-devops-platform-can-help-you-achieve-devsecops",{"title":3032,"description":3033,"ogTitle":3032,"ogDescription":3033,"noIndex":6,"ogImage":3034,"ogUrl":3035,"ogSiteName":667,"ogType":668,"canonicalUrls":3035,"schema":3036},"One DevOps platform can help you achieve DevSecOps","GitLab drives innovation in the AST market to secure cloud-native applications.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679348/Blog/Hero%20Images/locks.jpg","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":3032,"description":3033,"authors":3038,"heroImage":3034,"date":3039,"body":3040,"category":675,"tags":3041},[780],"2022-05-09","\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",[1280,9,2003,675,1179],{"slug":3043,"featured":6,"template":679},"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":3049,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3050,"content":3056,"config":3061,"_id":3063,"_type":14,"title":3064,"_source":16,"_file":3065,"_stem":3066,"_extension":19},"/en-us/blog/origin-of-devsecops-platform-category",{"title":3051,"description":3052,"ogTitle":3051,"ogDescription":3052,"noIndex":6,"ogImage":3053,"ogUrl":3054,"ogSiteName":667,"ogType":668,"canonicalUrls":3054,"schema":3055},"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":3051,"description":3052,"authors":3057,"heroImage":3053,"date":3058,"body":3059,"category":975,"tags":3060},[1712],"2023-08-30","\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",[975,1019,475,9],{"slug":3062,"featured":6,"template":679},"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":3068,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3069,"content":3075,"config":3081,"_id":3083,"_type":14,"title":3084,"_source":16,"_file":3085,"_stem":3086,"_extension":19},"/en-us/blog/our-step-by-step-guide-to-evaluating-runtime-security-tools",{"title":3070,"description":3071,"ogTitle":3070,"ogDescription":3071,"noIndex":6,"ogImage":3072,"ogUrl":3073,"ogSiteName":667,"ogType":668,"canonicalUrls":3073,"schema":3074},"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":3070,"description":3071,"authors":3076,"heroImage":3072,"date":3078,"body":3079,"category":675,"tags":3080},[3077,908],"Hiroki Suezawa","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",[675,9,1019],{"slug":3082,"featured":6,"template":679},"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":3088,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3089,"content":3095,"config":3100,"_id":3103,"_type":14,"title":3104,"_source":16,"_file":3105,"_stem":3106,"_extension":19},"/en-us/blog/overcome-ai-sprawl-with-a-value-stream-management-approach",{"title":3090,"description":3091,"ogTitle":3090,"ogDescription":3091,"noIndex":91,"ogImage":3092,"ogUrl":3093,"ogSiteName":667,"ogType":668,"canonicalUrls":3093,"schema":3094},"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.","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":3090,"description":3091,"authors":3096,"heroImage":3092,"date":3097,"body":3098,"category":10,"tags":3099},[2961],"2025-01-06","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/).",[9,997,1020],{"slug":3101,"featured":6,"template":679,"externalUrl":3102},"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":3108,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3109,"content":3115,"config":3121,"_id":3123,"_type":14,"title":3124,"_source":16,"_file":3125,"_stem":3126,"_extension":19},"/en-us/blog/oxeye-joins-gitlab-to-advance-application-security-capabilities",{"title":3110,"description":3111,"ogTitle":3110,"ogDescription":3111,"noIndex":6,"ogImage":3112,"ogUrl":3113,"ogSiteName":667,"ogType":668,"canonicalUrls":3113,"schema":3114},"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":3110,"description":3111,"authors":3116,"heroImage":3112,"date":3118,"body":3119,"category":975,"tags":3120},[1868,3117],"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.",[675,975,9],{"slug":3122,"featured":91,"template":679},"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":3128,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3129,"content":3135,"config":3141,"_id":3143,"_type":14,"title":3144,"_source":16,"_file":3145,"_stem":3146,"_extension":19},"/en-us/blog/quick-setup-of-a-gke-cluster-with-argocd-pre-installed-using-terraform",{"title":3130,"description":3131,"ogTitle":3130,"ogDescription":3131,"noIndex":6,"ogImage":3132,"ogUrl":3133,"ogSiteName":667,"ogType":668,"canonicalUrls":3133,"schema":3134},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749665989/Blog/Hero%20Images/AdobeStock_618473457.jpg","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":3130,"description":3131,"authors":3136,"heroImage":3132,"date":3137,"body":3138,"category":890,"tags":3139},[802,887],"2024-01-31","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",[530,3140,109,9,1240],"GKE",{"slug":3142,"featured":6,"template":679},"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":3148,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3149,"content":3152,"config":3158,"_id":3160,"_type":14,"title":3161,"_source":16,"_file":3162,"_stem":3163,"_extension":19},"/en-us/blog/reduce-the-load-on-gitlab-gitaly-with-bundle-uri",{"noIndex":6,"title":3150,"description":3151},"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":3150,"description":3151,"heroImage":3153,"date":1790,"body":3154,"category":829,"tags":3155,"authors":3156},"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.",[829,9,1022],[3157],"Olivier Campeau",{"featured":6,"template":679,"slug":3159},"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":3165,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3166,"content":3172,"config":3177,"_id":3179,"_type":14,"title":3180,"_source":16,"_file":3181,"_stem":3182,"_extension":19},"/en-us/blog/refactor-code-into-modern-languages-with-ai-powered-gitlab-duo",{"title":3167,"description":3168,"ogTitle":3167,"ogDescription":3168,"noIndex":6,"ogImage":3169,"ogUrl":3170,"ogSiteName":667,"ogType":668,"canonicalUrls":3170,"schema":3171},"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://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/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":3167,"description":3168,"authors":3173,"heroImage":3169,"date":3174,"body":3175,"category":762,"tags":3176},[1299],"2024-08-26","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",[698,808,9],{"slug":3178,"featured":6,"template":679},"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":3184,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3185,"content":3190,"config":3195,"_id":3197,"_type":14,"title":3198,"_source":16,"_file":3199,"_stem":3200,"_extension":19},"/en-us/blog/refactoring-a-ci-cd-template-to-a-ci-cd-component",{"title":3186,"description":3187,"ogTitle":3186,"ogDescription":3187,"noIndex":6,"ogImage":3132,"ogUrl":3188,"ogSiteName":667,"ogType":668,"canonicalUrls":3188,"schema":3189},"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://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":3186,"description":3187,"authors":3191,"heroImage":3132,"date":3192,"body":3193,"category":890,"tags":3194},[1593],"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",[109,9,808],{"slug":3196,"featured":91,"template":679},"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":3202,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3203,"content":3209,"config":3215,"_id":3217,"_type":14,"title":3218,"_source":16,"_file":3219,"_stem":3220,"_extension":19},"/en-us/blog/remote-development-beta",{"title":3204,"description":3205,"ogTitle":3204,"ogDescription":3205,"noIndex":6,"ogImage":3206,"ogUrl":3207,"ogSiteName":667,"ogType":668,"canonicalUrls":3207,"schema":3208},"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":3204,"description":3205,"authors":3210,"heroImage":3206,"date":3211,"body":3212,"category":890,"tags":3213},[1849],"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",[808,9,997,934,3214,784],"contributors",{"slug":3216,"featured":6,"template":679},"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":3222,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3223,"content":3229,"config":3236,"_id":3238,"_type":14,"title":3239,"_source":16,"_file":3240,"_stem":3241,"_extension":19},"/en-us/blog/revisiting-the-variables-management-workflow",{"title":3224,"description":3225,"ogTitle":3224,"ogDescription":3225,"noIndex":6,"ogImage":3226,"ogUrl":3227,"ogSiteName":667,"ogType":668,"canonicalUrls":3227,"schema":3228},"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":3224,"description":3225,"authors":3230,"heroImage":3226,"date":3232,"body":3233,"category":890,"tags":3234},[3231],"Veethika Mishra","2024-02-26","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",[109,3235,9,1280],"UX",{"slug":3237,"featured":91,"template":679},"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":3243,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3244,"content":3249,"config":3254,"_id":3256,"_type":14,"title":3257,"_source":16,"_file":3258,"_stem":3259,"_extension":19},"/en-us/blog/rise-of-protestware",{"title":3245,"description":3246,"ogTitle":3245,"ogDescription":3246,"noIndex":6,"ogImage":1430,"ogUrl":3247,"ogSiteName":667,"ogType":668,"canonicalUrls":3247,"schema":3248},"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":3245,"description":3246,"authors":3250,"heroImage":1430,"date":3251,"body":3252,"category":10,"tags":3253},[1436],"2023-05-09","\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",[9,2238,675,475],{"slug":3255,"featured":6,"template":679},"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":3261,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3262,"content":3268,"config":3274,"_id":3276,"_type":14,"title":3277,"_source":16,"_file":3278,"_stem":3279,"_extension":19},"/en-us/blog/seamlessly-migrate-from-jira-to-gitlab-with-jira2lab-at-scale",{"title":3263,"description":3264,"ogTitle":3263,"ogDescription":3264,"noIndex":6,"ogImage":3265,"ogUrl":3266,"ogSiteName":667,"ogType":668,"canonicalUrls":3266,"schema":3267},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749663129/Blog/Hero%20Images/blog-image-template-1800x945__28_.png","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":3263,"description":3264,"authors":3269,"heroImage":3265,"date":3271,"body":3272,"category":1378,"tags":3273},[3270],"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",[1380,109,9,700,829],{"slug":3275,"featured":91,"template":679},"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":3281,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3282,"content":3288,"config":3294,"_id":3296,"_type":14,"title":3297,"_source":16,"_file":3298,"_stem":3299,"_extension":19},"/en-us/blog/secure-by-design-principles-meet-devsecops-innovation-in-gitlab-17",{"title":3283,"description":3284,"ogTitle":3283,"ogDescription":3284,"noIndex":6,"ogImage":3285,"ogUrl":3286,"ogSiteName":667,"ogType":668,"canonicalUrls":3286,"schema":3287},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749676004/Blog/Hero%20Images/blog-image-template-1800x945__6_.png","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":3283,"description":3284,"authors":3289,"heroImage":3285,"date":3291,"body":3292,"category":675,"tags":3293},[3290],"Elisabeth Burrows","2024-06-05","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",[184,675,475,9],{"slug":3295,"featured":91,"template":679},"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":3301,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3302,"content":3307,"config":3313,"_id":3315,"_type":14,"title":3316,"_source":16,"_file":3317,"_stem":3318,"_extension":19},"/en-us/blog/secure-compliant-and-ai-powered-get-to-know-3-new-gitlab-features",{"title":3303,"description":3304,"ogTitle":3303,"ogDescription":3304,"noIndex":6,"ogImage":1995,"ogUrl":3305,"ogSiteName":667,"ogType":668,"canonicalUrls":3305,"schema":3306},"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":3303,"description":3304,"authors":3308,"heroImage":1995,"date":3310,"body":3311,"category":829,"tags":3312},[3309],"Jessica Hurwitz","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",[9,475,700,829,675],{"slug":3314,"featured":91,"template":679},"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":3320,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3321,"content":3327,"config":3331,"_id":3333,"_type":14,"title":3334,"_source":16,"_file":3335,"_stem":3336,"_extension":19},"/en-us/blog/secureflag-integrated-with-gitlab-for-rapid-vulnerability-remediation",{"title":3322,"description":3323,"ogTitle":3322,"ogDescription":3323,"noIndex":6,"ogImage":3324,"ogUrl":3325,"ogSiteName":667,"ogType":668,"canonicalUrls":3325,"schema":3326},"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":3322,"description":3323,"authors":3328,"heroImage":3324,"date":2197,"body":3329,"category":675,"tags":3330},[1554],"\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",[675,9,829,700],{"slug":3332,"featured":6,"template":679},"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":3338,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3339,"content":3344,"config":3350,"_id":3352,"_type":14,"title":3353,"_source":16,"_file":3354,"_stem":3355,"_extension":19},"/en-us/blog/self-managed-support-for-code-suggestions",{"title":3340,"description":3341,"ogTitle":3340,"ogDescription":3341,"noIndex":6,"ogImage":820,"ogUrl":3342,"ogSiteName":667,"ogType":668,"canonicalUrls":3342,"schema":3343},"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":3340,"description":3341,"authors":3345,"heroImage":820,"date":3347,"body":3348,"category":762,"tags":3349},[3346],"Roger Woo","2023-06-15","\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",[9,829,700,698],{"slug":3351,"featured":6,"template":679},"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":3357,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3358,"content":3364,"config":3368,"_id":3370,"_type":14,"title":3371,"_source":16,"_file":3372,"_stem":3373,"_extension":19},"/en-us/blog/six-reasons-cisco-learning-and-certifications-adopted-gitlab",{"title":3359,"description":3360,"ogTitle":3359,"ogDescription":3360,"noIndex":6,"ogImage":3361,"ogUrl":3362,"ogSiteName":667,"ogType":668,"canonicalUrls":3362,"schema":3363},"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":3359,"description":3360,"authors":3365,"heroImage":3361,"date":1633,"body":3366,"category":953,"tags":3367},[737],"\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",[9,955,698],{"slug":3369,"featured":6,"template":679},"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":3375,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3376,"content":3382,"config":3388,"_id":3390,"_type":14,"title":3391,"_source":16,"_file":3392,"_stem":3393,"_extension":19},"/en-us/blog/speed-security-devops",{"title":3377,"description":3378,"ogTitle":3377,"ogDescription":3378,"noIndex":6,"ogImage":3379,"ogUrl":3380,"ogSiteName":667,"ogType":668,"canonicalUrls":3380,"schema":3381},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749678356/Blog/Hero%20Images/balance-speed-security-devops.jpg","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":3377,"description":3378,"authors":3383,"heroImage":3379,"date":3385,"body":3386,"category":931,"tags":3387},[3384],"Vanessa Wegner","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",[675,1280,9],{"slug":3389,"featured":6,"template":679},"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":3395,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3396,"content":3401,"config":3406,"_id":3408,"_type":14,"title":3409,"_source":16,"_file":3410,"_stem":3411,"_extension":19},"/en-us/blog/streamline-devsecops-engineering-workflows-with-gitlab-duo",{"title":3397,"description":3398,"ogTitle":3397,"ogDescription":3398,"noIndex":6,"ogImage":2844,"ogUrl":3399,"ogSiteName":667,"ogType":668,"canonicalUrls":3399,"schema":3400},"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":3397,"description":3398,"authors":3402,"heroImage":2844,"date":3403,"body":3404,"category":762,"tags":3405},[1436],"2024-12-05","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!",[698,109,9,475,808,829],{"slug":3407,"featured":91,"template":679},"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":3413,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3414,"content":3420,"config":3425,"_id":3427,"_type":14,"title":3428,"_source":16,"_file":3429,"_stem":3430,"_extension":19},"/en-us/blog/structuring-the-gitlab-package-registry-for-enterprise-scale",{"title":3415,"description":3416,"ogTitle":3415,"ogDescription":3416,"noIndex":6,"ogImage":3417,"ogUrl":3418,"ogSiteName":667,"ogType":668,"canonicalUrls":3418,"schema":3419},"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":3415,"description":3416,"authors":3421,"heroImage":3417,"date":3422,"body":3423,"category":829,"tags":3424},[2040],"2025-02-19","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",[9,808,1240],{"slug":3426,"featured":91,"template":679},"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":3432,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3433,"content":3438,"config":3443,"_id":3445,"_type":14,"title":3446,"_source":16,"_file":3447,"_stem":3448,"_extension":19},"/en-us/blog/summarize-my-merge-request-review",{"title":3434,"description":3435,"ogTitle":3434,"ogDescription":3435,"noIndex":6,"ogImage":820,"ogUrl":3436,"ogSiteName":667,"ogType":668,"canonicalUrls":3436,"schema":3437},"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":3434,"description":3435,"authors":3439,"heroImage":820,"date":3440,"body":3441,"category":762,"tags":3442},[1573],"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",[9,829,700,698],{"slug":3444,"featured":6,"template":679},"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":3450,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3451,"content":3457,"config":3462,"_id":3464,"_type":14,"title":3465,"_source":16,"_file":3466,"_stem":3467,"_extension":19},"/en-us/blog/supercharge-productivity-with-gitlab-duo",{"title":3452,"description":3453,"ogTitle":3452,"ogDescription":3453,"noIndex":6,"ogImage":3454,"ogUrl":3455,"ogSiteName":667,"ogType":668,"canonicalUrls":3455,"schema":3456},"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":3452,"description":3453,"authors":3458,"heroImage":3454,"date":3459,"body":3460,"category":762,"tags":3461},[1436],"2023-07-20","\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",[9,475,698],{"slug":3463,"featured":6,"template":679},"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":3469,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3470,"content":3476,"config":3481,"_id":3483,"_type":14,"title":3484,"_source":16,"_file":3485,"_stem":3486,"_extension":19},"/en-us/blog/the-gitlab-quarterly-how-our-latest-beta-releases-support-developers",{"title":3471,"description":3472,"ogTitle":3471,"ogDescription":3472,"noIndex":6,"ogImage":3473,"ogUrl":3474,"ogSiteName":667,"ogType":668,"canonicalUrls":3474,"schema":3475},"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":3471,"description":3472,"authors":3477,"heroImage":3473,"date":3478,"body":3479,"category":10,"tags":3480},[867],"2023-01-24","\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",[1280,9,1020,700],{"slug":3482,"featured":6,"template":679},"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":3488,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3489,"content":3495,"config":3501,"_id":3503,"_type":14,"title":3504,"_source":16,"_file":3505,"_stem":3506,"_extension":19},"/en-us/blog/the-ultimate-guide-to-sboms",{"title":3490,"description":3491,"ogTitle":3490,"ogDescription":3491,"noIndex":6,"ogImage":3492,"ogUrl":3493,"ogSiteName":667,"ogType":668,"canonicalUrls":3493,"schema":3494},"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":3490,"description":3491,"authors":3496,"heroImage":3492,"date":3497,"body":3498,"category":675,"tags":3499,"updatedDate":3500},[780],"2022-10-25","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._",[675,9,1020,784,184],"2024-05-02",{"slug":3502,"featured":6,"template":679},"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":3508,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3509,"content":3514,"config":3519,"_id":3521,"_type":14,"title":3522,"_source":16,"_file":3523,"_stem":3524,"_extension":19},"/en-us/blog/there-is-no-mlops-without-devsecops",{"title":3510,"description":3511,"ogTitle":3510,"ogDescription":3511,"noIndex":6,"ogImage":1034,"ogUrl":3512,"ogSiteName":667,"ogType":668,"canonicalUrls":3512,"schema":3513},"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":3510,"description":3511,"authors":3515,"heroImage":1034,"date":3516,"body":3517,"category":762,"tags":3518},[2941],"2023-10-05","\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",[808,9,475,698],{"slug":3520,"featured":6,"template":679},"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":3526,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3527,"content":3532,"config":3537,"_id":3539,"_type":14,"title":3540,"_source":16,"_file":3541,"_stem":3542,"_extension":19},"/en-us/blog/top-10-gitlab-technical-blogs-of-2023",{"title":3528,"description":3529,"ogTitle":3528,"ogDescription":3529,"noIndex":6,"ogImage":946,"ogUrl":3530,"ogSiteName":667,"ogType":668,"canonicalUrls":3530,"schema":3531},"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":3528,"description":3529,"authors":3533,"heroImage":946,"date":3534,"body":3535,"category":10,"tags":3536},[780],"2024-01-09","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",[698,109,475,9,675,808],{"slug":3538,"featured":91,"template":679},"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":3544,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3545,"content":3551,"config":3559,"_id":3561,"_type":14,"title":3562,"_source":16,"_file":3563,"_stem":3564,"_extension":19},"/en-us/blog/top-ten-reasons-to-check-out-gitlab-virtual-commit",{"title":3546,"description":3547,"ogTitle":3546,"ogDescription":3547,"noIndex":6,"ogImage":3548,"ogUrl":3549,"ogSiteName":667,"ogType":668,"canonicalUrls":3549,"schema":3550},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749664102/Blog/Hero%20Images/gitlab-values-cover.png","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":3546,"description":3547,"authors":3552,"heroImage":3548,"date":3554,"body":3555,"category":3556,"tags":3557},[3553],"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","unfiltered",[1280,9,675,3558],"kubernetes",{"slug":3560,"featured":6,"template":679},"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":3566,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3567,"content":3572,"config":3577,"_id":3579,"_type":14,"title":3580,"_source":16,"_file":3581,"_stem":3582,"_extension":19},"/en-us/blog/training-and-deploying-ai-models-with-gitlab-and-vertex-ai",{"title":3568,"description":3569,"ogTitle":3568,"ogDescription":3569,"noIndex":6,"ogImage":820,"ogUrl":3570,"ogSiteName":667,"ogType":668,"canonicalUrls":3570,"schema":3571},"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":3568,"description":3569,"authors":3573,"heroImage":820,"date":929,"body":3575,"category":762,"tags":3576},[3574],"Regnard Raquedan","\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",[9,829,700,698],{"slug":3578,"featured":6,"template":679},"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":3584,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3585,"content":3591,"config":3597,"_id":3599,"_type":14,"title":3600,"_source":16,"_file":3601,"_stem":3602,"_extension":19},"/en-us/blog/tutorial-automated-release-and-release-notes-with-gitlab",{"title":3586,"description":3587,"ogTitle":3586,"ogDescription":3587,"noIndex":6,"ogImage":3588,"ogUrl":3589,"ogSiteName":667,"ogType":668,"canonicalUrls":3589,"schema":3590},"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://res.cloudinary.com/about-gitlab-com/image/upload/v1749659978/Blog/Hero%20Images/automation.png","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":3586,"description":3587,"authors":3592,"heroImage":3588,"date":2600,"body":3594,"category":829,"tags":3595,"updatedDate":3596},[3593],"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",[808,806,109,1280,9,1022],"2025-06-05",{"slug":3598,"featured":6,"template":679},"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":3604,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3605,"content":3611,"config":3615,"_id":3617,"_type":14,"title":3618,"_source":16,"_file":3619,"_stem":3620,"_extension":19},"/en-us/blog/tutorial-how-to-set-up-your-first-gitlab-ci-cd-component",{"title":3606,"description":3607,"ogTitle":3606,"ogDescription":3607,"noIndex":6,"ogImage":3608,"ogUrl":3609,"ogSiteName":667,"ogType":668,"canonicalUrls":3609,"schema":3610},"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":3606,"description":3607,"authors":3612,"heroImage":3608,"date":2657,"body":3613,"category":890,"tags":3614},[2772,802],"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",[109,808,9,1240],{"slug":3616,"featured":91,"template":679},"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":3622,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3623,"content":3628,"config":3633,"_id":3635,"_type":14,"title":3636,"_source":16,"_file":3637,"_stem":3638,"_extension":19},"/en-us/blog/tutorial-secure-bigquery-data-publishing-with-gitlab",{"title":3624,"description":3625,"ogTitle":3624,"ogDescription":3625,"noIndex":6,"ogImage":2652,"ogUrl":3626,"ogSiteName":667,"ogType":668,"canonicalUrls":3626,"schema":3627},"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":3624,"description":3625,"authors":3629,"heroImage":2652,"date":3630,"body":3631,"category":890,"tags":3632},[3574],"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.",[9,475,808,997,231,1021],{"slug":3634,"featured":91,"template":679},"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":3640,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3641,"content":3646,"config":3651,"_id":3653,"_type":14,"title":3654,"_source":16,"_file":3655,"_stem":3656,"_extension":19},"/en-us/blog/u-s-navy-black-pearl-lessons-in-championing-devsecops",{"title":3642,"description":3643,"ogTitle":3642,"ogDescription":3643,"noIndex":6,"ogImage":861,"ogUrl":3644,"ogSiteName":667,"ogType":668,"canonicalUrls":3644,"schema":3645},"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://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":3642,"description":3643,"authors":3647,"heroImage":861,"date":3648,"body":3649,"category":953,"tags":3650},[780],"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",[9,475,675,267,184],{"slug":3652,"featured":91,"template":679},"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":3658,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3659,"content":3665,"config":3669,"_id":3671,"_type":14,"title":3672,"_source":16,"_file":3673,"_stem":3674,"_extension":19},"/en-us/blog/ultimate-guide-to-ci-cd-fundamentals-to-advanced-implementation",{"title":3660,"description":3661,"ogTitle":3660,"ogDescription":3661,"noIndex":6,"ogImage":3662,"ogUrl":3663,"ogSiteName":667,"ogType":668,"canonicalUrls":3663,"schema":3664},"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":3660,"description":3661,"authors":3666,"heroImage":3662,"date":3097,"body":3667,"category":10,"tags":3668},[780],"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.",[109,9,475,808,675,829],{"slug":3670,"featured":91,"template":679},"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":3676,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3677,"content":3683,"config":3688,"_id":3690,"_type":14,"title":3691,"_source":16,"_file":3692,"_stem":3693,"_extension":19},"/en-us/blog/unlocking-agile-excellence-gitlab-epics-for-seamless-portfolio-management",{"title":3678,"description":3679,"ogTitle":3678,"ogDescription":3679,"noIndex":6,"ogImage":3680,"ogUrl":3681,"ogSiteName":667,"ogType":668,"canonicalUrls":3681,"schema":3682},"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":3678,"description":3679,"authors":3684,"heroImage":3680,"date":3685,"body":3686,"category":1378,"tags":3687},[1375,1613],"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.",[1380,9,475],{"slug":3689,"featured":91,"template":679},"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":3695,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3696,"content":3702,"config":3708,"_id":3710,"_type":14,"title":3711,"_source":16,"_file":3712,"_stem":3713,"_extension":19},"/en-us/blog/use-gitlab-duo-to-build-and-deploy-a-simple-quarkus-native-project",{"title":3697,"description":3698,"ogTitle":3697,"ogDescription":3698,"noIndex":6,"ogImage":3699,"ogUrl":3700,"ogSiteName":667,"ogType":668,"canonicalUrls":3700,"schema":3701},"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":3697,"description":3698,"authors":3703,"heroImage":3699,"date":3704,"body":3705,"category":762,"tags":3706},[1456],"2024-10-17","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.",[698,808,9,3707,700,829,109],"demo",{"slug":3709,"featured":91,"template":679},"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":3715,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3716,"content":3722,"config":3728,"_id":3730,"_type":14,"title":3731,"_source":16,"_file":3732,"_stem":3733,"_extension":19},"/en-us/blog/vestiaire-collective-on-moving-to-a-devsecops-platform",{"title":3717,"description":3718,"ogTitle":3717,"ogDescription":3718,"noIndex":6,"ogImage":3719,"ogUrl":3720,"ogSiteName":667,"ogType":668,"canonicalUrls":3720,"schema":3721},"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":3723,"description":3718,"authors":3724,"heroImage":3719,"date":3725,"body":3726,"category":953,"tags":3727},"Vestiaire Collective VP shares wins, insights, and what's next with DevSecOps migration",[2581],"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",[9,955,1020,806,807],{"slug":3729,"featured":6,"template":679},"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":3735,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3736,"content":3742,"config":3747,"_id":3749,"_type":14,"title":3750,"_source":16,"_file":3751,"_stem":3752,"_extension":19},"/en-us/blog/vulnerability-risk-prioritization-made-simple-with-gitlab",{"title":3737,"description":3738,"ogTitle":3737,"ogDescription":3738,"noIndex":6,"ogImage":3739,"ogUrl":3740,"ogSiteName":667,"ogType":668,"canonicalUrls":3740,"schema":3741},"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":3737,"description":3738,"authors":3743,"heroImage":3739,"date":3744,"body":3745,"category":675,"tags":3746},[1514],"2025-03-12","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)",[808,675,9],{"slug":3748,"featured":91,"template":679},"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":3754,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3755,"content":3761,"config":3766,"_id":3768,"_type":14,"title":3769,"_source":16,"_file":3770,"_stem":3771,"_extension":19},"/en-us/blog/what-is-a-large-language-model-llm",{"title":3756,"description":3757,"ogTitle":3756,"ogDescription":3757,"noIndex":6,"ogImage":3758,"ogUrl":3759,"ogSiteName":667,"ogType":668,"canonicalUrls":3759,"schema":3760},"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":3756,"description":3757,"authors":3762,"heroImage":3758,"date":3763,"body":3764,"category":762,"tags":3765},[1593],"2025-05-29","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)",[698,9],{"slug":3767,"featured":6,"template":679},"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":3773,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3774,"content":3780,"config":3786,"_id":3788,"_type":14,"title":3789,"_source":16,"_file":3790,"_stem":3791,"_extension":19},"/en-us/blog/what-is-git-the-ultimate-guide-to-gits-role-and-functionality",{"title":3775,"description":3776,"ogTitle":3775,"ogDescription":3776,"noIndex":6,"ogImage":3777,"ogUrl":3778,"ogSiteName":667,"ogType":668,"canonicalUrls":3778,"schema":3779},"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":3775,"description":3776,"authors":3781,"heroImage":3777,"date":3782,"body":3783,"category":3784,"tags":3785},[2292],"2024-11-14","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.","open-source",[1022,9,784],{"slug":3787,"featured":6,"template":679},"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":3793,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3794,"content":3800,"config":3806,"_id":3808,"_type":14,"title":3809,"_source":16,"_file":3810,"_stem":3811,"_extension":19},"/en-us/blog/what-the-digital-operational-resilience-act-means-for-banks",{"title":3795,"description":3796,"ogTitle":3795,"ogDescription":3796,"noIndex":6,"ogImage":3797,"ogUrl":3798,"ogSiteName":667,"ogType":668,"canonicalUrls":3798,"schema":3799},"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":3795,"description":3796,"authors":3801,"heroImage":3797,"date":3803,"body":3804,"category":675,"tags":3805},[3802,2123],"Joshua Carroll","2025-01-15","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",[551,675,475,9],{"slug":3807,"featured":6,"template":679},"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":3813,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3814,"content":3820,"config":3825,"_id":3827,"_type":14,"title":3828,"_source":16,"_file":3829,"_stem":3830,"_extension":19},"/en-us/blog/why-are-organizations-moving-to-a-unified-devsecops-platform",{"title":3815,"description":3816,"ogTitle":3815,"ogDescription":3816,"noIndex":6,"ogImage":3817,"ogUrl":3818,"ogSiteName":667,"ogType":668,"canonicalUrls":3818,"schema":3819},"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":3815,"description":3816,"authors":3821,"heroImage":3817,"date":3822,"body":3823,"category":10,"tags":3824},[1593],"2025-06-02","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/)",[9,475,829],{"slug":3826,"featured":6,"template":679},"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":3832,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3833,"content":3839,"config":3846,"_id":3848,"_type":14,"title":3849,"_source":16,"_file":3850,"_stem":3851,"_extension":19},"/en-us/blog/why-gitlab-is-deprecating-compliance-pipelines-in-favor-of-security-policies",{"title":3834,"description":3835,"ogTitle":3834,"ogDescription":3835,"noIndex":6,"ogImage":3836,"ogUrl":3837,"ogSiteName":667,"ogType":668,"canonicalUrls":3837,"schema":3838},"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":3840,"description":3835,"authors":3841,"heroImage":3836,"date":3843,"body":3844,"category":675,"tags":3845},"Why GitLab is deprecating compliance pipelines in favor of security policies",[3842],"Ian Khor","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.",[675,808,9,109],{"slug":3847,"featured":91,"template":679},"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":3853,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3854,"content":3859,"config":3864,"_id":3866,"_type":14,"title":3867,"_source":16,"_file":3868,"_stem":3869,"_extension":19},"/en-us/blog/why-gitlab-self-managed-is-the-perfect-partner-for-the-public-sector",{"title":3855,"description":3856,"ogTitle":3855,"ogDescription":3856,"noIndex":6,"ogImage":1747,"ogUrl":3857,"ogSiteName":667,"ogType":668,"canonicalUrls":3857,"schema":3858},"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":3855,"description":3856,"authors":3860,"heroImage":1747,"date":3861,"body":3862,"category":10,"tags":3863},[780],"2023-12-13","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/solutions/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",[9,1280,3558,1380,184],{"slug":3865,"featured":6,"template":679},"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":3871,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3872,"content":3877,"config":3882,"_id":3884,"_type":14,"title":3885,"_source":16,"_file":3886,"_stem":3887,"_extension":19},"/en-us/blog/why-hackerone-gets-love-letters-from-developers",{"title":3873,"description":3874,"ogTitle":3873,"ogDescription":3874,"noIndex":6,"ogImage":2689,"ogUrl":3875,"ogSiteName":667,"ogType":668,"canonicalUrls":3875,"schema":3876},"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://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":3873,"description":3874,"authors":3878,"heroImage":2689,"date":3879,"body":3880,"category":953,"tags":3881},[737],"2023-11-14","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/)._",[9,475,698,955],{"slug":3883,"featured":91,"template":679},"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":3889,"_dir":244,"_draft":6,"_partial":6,"_locale":7,"seo":3890,"content":3896,"config":3900,"_id":3902,"_type":14,"title":3903,"_source":16,"_file":3904,"_stem":3905,"_extension":19},"/en-us/blog/3-gitlab-features-to-level-up-devsecops-workflows",{"title":3891,"description":3892,"ogTitle":3891,"ogDescription":3892,"noIndex":6,"ogImage":3893,"ogUrl":3894,"ogSiteName":667,"ogType":668,"canonicalUrls":3894,"schema":3895},"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":3891,"description":3892,"authors":3897,"heroImage":3893,"date":2582,"body":3898,"category":829,"tags":3899},[1691],"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).",[829,700,9,675,109],{"slug":3901,"featured":91,"template":679},"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",19,[660,684,707,727,749,770,791,815,836],1752588089380]