[{"data":1,"prerenderedAt":717},["ShallowReactive",2],{"/en-us/blog/how-gitlab-duo-agent-platform-transforms-dataops/":3,"navigation-en-us":33,"banner-en-us":461,"footer-en-us":478,"Dennis van Rooijen":688,"next-steps-en-us":702},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"config":11,"content":15,"_id":26,"_type":27,"title":28,"_source":29,"_file":30,"_stem":31,"_extension":32},"/en-us/blog/how-gitlab-duo-agent-platform-transforms-dataops","blog",false,"",{"title":9,"description":10},"How GitLab Duo Agent Platform transforms DataOps","Explore how to turn hours of manual coding into minutes of automated generation with this comprehensive dbt model creation walkthrough.",{"slug":12,"featured":13,"template":14},"how-gitlab-duo-agent-platform-transforms-dataops",true,"BlogPost",{"title":9,"description":10,"authors":16,"heroImage":18,"date":19,"category":20,"tags":21,"body":25},[17],"Dennis van Rooijen","blog/hero%20images/workflow_1800x945.png","2025-09-16","ai-ml",[22,23,24],"product","tutorial","features","Creating dbt models manually is a tedious process that can consume hours of a data engineer's time. Especially when no (big) business transformations are made, it is not the most attractive part of an engineer's work with data.\n\nBut what if you could automate this entire process? In this walkthrough, I'll show you exactly how [GitLab Duo Agent Platform](https://about.gitlab.com/gitlab-duo/agent-platform/) can generate comprehensive dbt models in just minutes, complete with proper structure, tests, and documentation.\n\n## What we're building\n\nOur marketing team wants to effectively manage and optimize advertising investments. One of the advertising platforms is Reddit, so, therefore, we are extracting data from the Reddit Ads API to our enterprise [Data Platform](https://handbook.gitlab.com/handbook/enterprise-data/platform/) Snowflake. At GitLab, we have three layers of storage:\n\n1. `raw` layer - first landing point for unprocessed data from external sources; not ready for business use\n2. `prep` layer - first transformation layer with source models; still not ready for general business use\n3. `prod` layer - final transformed data ready for business use and Tableau reporting\n\n![Chart of storage layers](https://res.cloudinary.com/about-gitlab-com/image/upload/v1758030995/zo7vespktzfdtdtiauz7.png)\n\nFor this walkthrough, data has already landed in the raw layer by our extraction solution Fivetran, and we'll generate dbt models that handle the data through the `prep` layer to the `prod` layer.\n\nWithout having to write a single line of dbt code ourselves, by the end of the walkthrough we will have:\n\n- **Source models** in the prep layer\n- **Workspace models** in the prod layer\n- **Complete dbt configurations** for all 13 tables (which includes 112 columns) in the Reddit Ads dataset\n- **Test queries** to validate the outcomes\n\nThe entire process will take less than 10 minutes, compared to the hours it would typically require manually. Here are the steps to follow:\n\n## 1. Prepare the data structure\n\nBefore GitLab Duo can generate our models, it needs to understand the complete table structure. The key is running a query against Snowflake's information schema, because we are currently investigating how to connect GitLab Duo via Model Context Protocol ([MCP](https://about.gitlab.com/topics/ai/model-context-protocol/)) to our Snowflake instance:\n\n```sql\nSELECT \n    table_name,\n    column_name,\n    data_type,\n    is_nullable,\n    CASE \n        WHEN is_nullable = 'NO' THEN 'PRIMARY_KEY'\n        ELSE NULL \n    END as key_type\nFROM raw.information_schema.columns\nWHERE table_schema = 'REDDIT_ADS'\nORDER BY table_name, ordinal_position;\n```\n\nThis query captures:\n\n- All table and column names\n- Data types for proper model structure\n- Nullable constraints\n- Primary key identification (non-nullable columns in this dataset)\n\n**Pro tip:** In the Reddit Ads dataset, all non-nullable columns serve as primary keys — a pattern. I validated by checking tables like `ad_group`, which has two non-nullable columns (`account_id` and `id`) that are both marked as primary keys. Running this query returned 112 rows of metadata that I exported as a CSV file for model generation. While this manual step works well today, we're investigating a direct GitLab Duo integration with our Data Platform via MCP to automate this process entirely.\n\n## 2. Set up GitLab Duo\n\nThere are two ways to interact with [GitLab Duo](https://docs.gitlab.com/user/get_started/getting_started_gitlab_duo/):\n\n1. **Web UI chat function**\n2. **Visual Studio Code plugin**\n\nI chose the VS Code plugin because I can run the dbt models locally to test them.\n\n## 3. Enter the 'magic' prompt\n\nHere's the exact prompt I used to generate all the dbt code:\n\n```yaml\nCreate dbt models for all the tables in the file structure.csv.\n\nI want to have the source models created, with a filter that dedupes the data based on the primary key. Create these in a new folder reddit_ads.\nI want to have workspace models created and store these in the workspace_marketing schema.\n\nTake this MR as example: [I've referenced to previous source implementation]. Here is the same done for Source A, but now it needs to be done for Reddit Ads. \n\nPlease check the dbt style guide when creating the code: https://handbook.gitlab.com/handbook/enterprise-data/platform/dbt-guide/\n```\n\nKey elements that made this prompt effective:\n\n- **Clear specifications** for both source and workspace models.\n- **Reference example** from a previous similar merge request.\n- **Style guide reference** to ensure code quality and consistency.\n- **Specific schema targeting** for proper organization.\n\n## 4. GitLab Duo's process\n\nAfter submitting the prompt, GitLab Duo got to work. The entire generation process took a few minutes, during which GitLab Duo:\n\n1. **Read and analyzed** the CSV input file.\n2. **Examined table structures** from the metadata.\n3. **Referenced our dbt style guide** for coding standards.\n4. **Took similar merge request into account** to properly structure.\n5. **Generated source models** for all 13 tables.\n6. **Created workspace models** for all 13 tables.\n7. **Generated supporting dbt files**:\n   - `sources.yml` configuration.\n   - `schema.yml` files with tests and documentation.\n   - Updated `dbt_project.yml` with schema references.\n\n## The results\n\nThe output was remarkable:\n\n- **1 modified file:** dbt_project.yml (added reddit_ads schema configuration)\n- **29 new files:**\n  - **26 dbt models** (13 source + 13 workspace)\n  - **3 YAML files**\n- **Nearly 900 lines of code** generated automatically\n- **Built-in data tests,** including unique constraints on primary key columns\n- **Generic descriptions** for all models and columns\n- **Proper deduplication logic** in source models\n- **Clean, consistent code structure** following the GitLab dbt style guide\n\n```yaml\ntransform/snowflake-dbt/\n├── dbt_project.yml                                                    [MODIFIED]\n└── models/\n    ├── sources/\n    │   └── reddit_ads/\n    │       ├── reddit_ads_ad_group_source.sql                        [NEW]\n    │       ├── reddit_ads_ad_source.sql                              [NEW]\n    │       ├── reddit_ads_business_account_source.sql                [NEW]\n    │       ├── reddit_ads_campaign_source.sql                        [NEW]\n    │       ├── reddit_ads_custom_audience_history_source.sql         [NEW]\n    │       ├── reddit_ads_geolocation_source.sql                     [NEW]\n    │       ├── reddit_ads_interest_source.sql                        [NEW]\n    │       ├── reddit_ads_targeting_community_source.sql             [NEW]\n    │       ├── reddit_ads_targeting_custom_audience_source.sql       [NEW]\n    │       ├── reddit_ads_targeting_device_source.sql                [NEW]\n    │       ├── reddit_ads_targeting_geolocation_source.sql           [NEW]\n    │       ├── reddit_ads_targeting_interest_source.sql              [NEW]\n    │       ├── reddit_ads_time_zone_source.sql                       [NEW]\n    │       ├── schema.yml                                            [NEW]\n    │       └── sources.yml                                           [NEW]\n    └── workspaces/\n        └── workspace_marketing/\n            └── reddit_ads/\n                ├── schema.yml                                        [NEW]\n                ├── wk_reddit_ads_ad.sql                              [NEW]\n                ├── wk_reddit_ads_ad_group.sql                        [NEW]\n                ├── wk_reddit_ads_business_account.sql                [NEW]\n                ├── wk_reddit_ads_campaign.sql                        [NEW]\n                ├── wk_reddit_ads_custom_audience_history.sql         [NEW]\n                ├── wk_reddit_ads_geolocation.sql                     [NEW]\n                ├── wk_reddit_ads_interest.sql                        [NEW]\n                ├── wk_reddit_ads_targeting_community.sql             [NEW]\n                ├── wk_reddit_ads_targeting_custom_audience.sql       [NEW]\n                ├── wk_reddit_ads_targeting_device.sql                [NEW]\n                ├── wk_reddit_ads_targeting_geolocation.sql           [NEW]\n                ├── wk_reddit_ads_targeting_interest.sql              [NEW]\n                └── wk_reddit_ads_time_zone.sql                       [NEW]\n```\n\n### Sample generated code\n\nHere's an example of the generated code quality. For the `time_zone` table, GitLab Duo created:\n\n**Prep Layer Source Model**\n\n```sql\nWITH source AS (\n  SELECT *\n  FROM {{ source('reddit_ads','time_zone') }}\n  QUALIFY ROW_NUMBER() OVER (PARTITION BY id ORDER BY _fivetran_synced DESC) = 1\n),\n\nrenamed AS (\n  SELECT\n    id::VARCHAR                               AS time_zone_id,\n    code::VARCHAR                             AS time_zone_code,\n    dst_offset::NUMBER                        AS time_zone_dst_offset,\n    is_dst_active::BOOLEAN                    AS is_time_zone_dst_active,\n    name::VARCHAR                             AS time_zone_name,\n    offset::NUMBER                            AS time_zone_offset,\n    _fivetran_synced::TIMESTAMP               AS fivetran_synced_at\n  FROM source\n)\n\nSELECT * FROM renamed\n```\n\n**Schema.yml**\n\n```yaml\nmodels:\n  - name: reddit_ads_time_zone_source\n    description: Time zone data from Reddit Ads system\n    columns:\n      - name: time_zone_id\n        description: Unique identifier for time zone records\n        data_tests:\n          - unique\n          - not_null\n      - name: time_zone_code\n        description: Code for the time zone\n      - name: time_zone_dst_offset\n        description: Daylight saving time offset for the time zone\n      - name: is_time_zone_dst_active\n        description: Flag indicating if daylight saving time is active\n      - name: time_zone_name\n        description: Name of the time zone\n      - name: time_zone_offset\n        description: Offset for the time zone\n      - name: fivetran_synced_at\n        description: Timestamp when the record was last synced by Fivetran\n```\n\n**Source.yml**\n\n```yaml\nsources:\n  - name: reddit_ads\n    database: RAW\n    schema: reddit_ads\n    loaded_at_field: _fivetran_synced\n    loader: fivetran\n    description: Reddit Ads data\n\n    quoting:\n      database: true\n      schema: false\n      identifier: false\n\n    tables:\n      - name: time_zone\n```\n\n**Workspace Model**\n\n```sql\nWITH source AS (\n  SELECT *\n  FROM {{ ref('reddit_ads_time_zone_source') }}\n)\n\nSELECT * FROM source\n```\n\n## 5. Quality validation\n\nNow that the code looks good, I pushed it to the MR and executed [CI test pipeline](https://handbook.gitlab.com/handbook/enterprise-data/platform/ci-jobs/#build_changes) to test the code and validate the outcome. I asked GitLab Duo to create a validation query:\n\n```yaml\nCreate a test query to test the row counts between the raw layer and the workspace layer. Keep in mind that we do deduplication, so we can compare both using distinct on the primary keys.\n```\n\nThe AI generated a comprehensive validation query that:\n\n- Compared row counts between raw and workspace layers.\n- Accounted for deduplication logic.\n- Tested all 13 tables.\n- Calculated data retention percentages.\n\n\u003Cdetails>\n\u003Csummary>Generated SQL Test query\u003C/summary>\n\n```sql\n-- Reddit Ads Row Count Validation Test\n-- Compares distinct counts between RAW layer and WORKSPACE_MARKETING layer\n-- Accounts for deduplication logic in source models\n\nWITH raw_counts AS (\n  -- Single primary key tables\n  SELECT 'ad' AS table_name, COUNT(DISTINCT id) AS raw_count\n  FROM RAW.REDDIT_ADS.AD\n  \n  UNION ALL\n  \n  SELECT 'business_account' AS table_name, COUNT(DISTINCT id) AS raw_count\n  FROM RAW.REDDIT_ADS.BUSINESS_ACCOUNT\n  \n  UNION ALL\n  \n  SELECT 'campaign' AS table_name, COUNT(DISTINCT id) AS raw_count\n  FROM RAW.REDDIT_ADS.CAMPAIGN\n  \n  UNION ALL\n  \n  SELECT 'custom_audience_history' AS table_name, COUNT(DISTINCT id) AS raw_count\n  FROM RAW.REDDIT_ADS.CUSTOM_AUDIENCE_HISTORY\n  \n  UNION ALL\n  \n  SELECT 'geolocation' AS table_name, COUNT(DISTINCT id) AS raw_count\n  FROM RAW.REDDIT_ADS.GEOLOCATION\n  \n  UNION ALL\n  \n  SELECT 'interest' AS table_name, COUNT(DISTINCT id) AS raw_count\n  FROM RAW.REDDIT_ADS.INTEREST\n  \n  UNION ALL\n  \n  SELECT 'time_zone' AS table_name, COUNT(DISTINCT id) AS raw_count\n  FROM RAW.REDDIT_ADS.TIME_ZONE\n  \n  -- Composite primary key tables\n  UNION ALL\n  \n  SELECT 'ad_group' AS table_name, COUNT(DISTINCT CONCAT(account_id, '|', id)) AS raw_count\n  FROM RAW.REDDIT_ADS.AD_GROUP\n  \n  UNION ALL\n  \n  SELECT 'targeting_community' AS table_name, COUNT(DISTINCT CONCAT(ad_group_id, '|', community_id)) AS raw_count\n  FROM RAW.REDDIT_ADS.TARGETING_COMMUNITY\n  \n  UNION ALL\n  \n  SELECT 'targeting_custom_audience' AS table_name, COUNT(DISTINCT CONCAT(ad_group_id, '|', custom_audience_id)) AS raw_count\n  FROM RAW.REDDIT_ADS.TARGETING_CUSTOM_AUDIENCE\n  \n  UNION ALL\n  \n  SELECT 'targeting_device' AS table_name, COUNT(DISTINCT _fivetran_id) AS raw_count\n  FROM RAW.REDDIT_ADS.TARGETING_DEVICE\n  \n  UNION ALL\n  \n  SELECT 'targeting_geolocation' AS table_name, COUNT(DISTINCT CONCAT(ad_group_id, '|', geolocation_id)) AS raw_count\n  FROM RAW.REDDIT_ADS.TARGETING_GEOLOCATION\n  \n  UNION ALL\n  \n  SELECT 'targeting_interest' AS table_name, COUNT(DISTINCT CONCAT(ad_group_id, '|', interest_id)) AS raw_count\n  FROM RAW.REDDIT_ADS.TARGETING_INTEREST\n),\n\nworkspace_counts AS (\n  -- Workspace layer counts using primary keys from schema.yml\n  SELECT 'ad' AS table_name, COUNT(DISTINCT ad_id) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_AD\n  \n  UNION ALL\n  \n  SELECT 'business_account' AS table_name, COUNT(DISTINCT business_account_id) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_BUSINESS_ACCOUNT\n  \n  UNION ALL\n  \n  SELECT 'campaign' AS table_name, COUNT(DISTINCT campaign_id) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_CAMPAIGN\n  \n  UNION ALL\n  \n  SELECT 'custom_audience_history' AS table_name, COUNT(DISTINCT custom_audience_id) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_CUSTOM_AUDIENCE_HISTORY\n  \n  UNION ALL\n  \n  SELECT 'geolocation' AS table_name, COUNT(DISTINCT geolocation_id) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_GEOLOCATION\n  \n  UNION ALL\n  \n  SELECT 'interest' AS table_name, COUNT(DISTINCT interest_id) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_INTEREST\n  \n  UNION ALL\n  \n  SELECT 'time_zone' AS table_name, COUNT(DISTINCT time_zone_id) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_TIME_ZONE\n  \n  -- Composite primary key tables\n  UNION ALL\n  \n  SELECT 'ad_group' AS table_name, COUNT(DISTINCT CONCAT(ad_group_account_id, '|', ad_group_id)) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_AD_GROUP\n  \n  UNION ALL\n  \n  SELECT 'targeting_community' AS table_name, COUNT(DISTINCT CONCAT(targeting_community_ad_group_id, '|', targeting_community_id)) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_TARGETING_COMMUNITY\n  \n  UNION ALL\n  \n  SELECT 'targeting_custom_audience' AS table_name, COUNT(DISTINCT CONCAT(targeting_custom_audience_ad_group_id, '|', targeting_custom_audience_id)) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_TARGETING_CUSTOM_AUDIENCE\n  \n  UNION ALL\n  \n  SELECT 'targeting_device' AS table_name, COUNT(DISTINCT targeting_device_fivetran_id) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_TARGETING_DEVICE\n  \n  UNION ALL\n  \n  SELECT 'targeting_geolocation' AS table_name, COUNT(DISTINCT CONCAT(targeting_geolocation_ad_group_id, '|', targeting_geolocation_id)) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_TARGETING_GEOLOCATION\n  \n  UNION ALL\n  \n  SELECT 'targeting_interest' AS table_name, COUNT(DISTINCT CONCAT(targeting_interest_ad_group_id, '|', targeting_interest_id)) AS workspace_count\n  FROM REDDIT_DBT_MODEL_GENERATION_PROD.WORKSPACE_MARKETING.WK_REDDIT_ADS_TARGETING_INTEREST\n)\n\n-- Final comparison with validation results\nSELECT \n  r.table_name,\n  r.raw_count,\n  w.workspace_count,\n  r.raw_count - w.workspace_count AS count_difference,\n  CASE \n    WHEN r.raw_count = w.workspace_count THEN '✅ PASS'\n    WHEN r.raw_count > w.workspace_count THEN '⚠️ RAW > WORKSPACE (Expected due to deduplication)'\n    ELSE '❌ FAIL - WORKSPACE > RAW (Unexpected)'\n  END AS validation_status,\n  ROUND((w.workspace_count::FLOAT / r.raw_count::FLOAT) * 100, 2) AS data_retention_percentage\nFROM raw_counts r\nJOIN workspace_counts w ON r.table_name = w.table_name\nORDER BY r.table_name;\n```\n\n\u003C/details>\n\n![query results table](https://res.cloudinary.com/about-gitlab-com/image/upload/v1758030995/guicjhzwvrz3czwjs3xo.png)\n\nRunning this query showed:\n\n- **Zero differences** in row counts after deduplication\n- **100% data retention** across all tables\n- **All tests passed** successfully\n\n## The bottom line: Massive time savings\n\n- **Traditional approach:** 6-8 hours of manual coding, testing, and debugging\n\n- **GitLab Duo approach:** 6-8 minutes of generation + review time\n\nThis represents a 60x improvement in developer efficiency (from 6-8 hours to 6-8 minutes), while maintaining high code quality.\n\n## Best practices for success\n\nBased on this experience, here are key recommendations:\n\n### Prepare your metadata\n\n- Extract complete table structures including data types and constraints.\n- Identify primary keys and relationships upfront.\n- Export clean, well-formatted CSV input files.\n\n**Note:** By connecting GitLab Duo via MCP to your (meta)data, you could exclude this manual step.\n\n### Provide clear context\n\n- Reference existing example MRs when possible.\n- Specify your coding standards and style guides.\n- Be explicit about folder structure and naming conventions.\n\n### Validate thoroughly\n\n- Always create validation queries for data integrity.\n- Test locally before merging.\n- Run your CI/CD pipeline to catch any issues.\n\n### Leverage AI for follow-up tasks\n\n- Generate test queries automatically.\n- Create documentation templates.\n- Build validation scripts.\n\n## What's next\n\nThis demonstration shows how AI-powered development tools like GitLab Duo are also transforming data engineering workflows. The ability to generate hundreds of lines of production-ready code in minutes —  complete with tests, documentation, and proper structure — represents a fundamental shift in how we approach repetitive development tasks.\n\nBy leveraging AI to handle the repetitive aspects of dbt model creation, data engineers can focus on higher-value activities like data modeling strategy, performance optimization, and business logic implementation.\n\n**Ready to try this yourself?** Start with a small dataset, prepare your metadata carefully, and watch as GitLab Duo transforms hours of work into minutes of automated generation.\n\n> [Trial GitLab Duo Agent Platform today.](https://about.gitlab.com/gitlab-duo/agent-platform/)\n\n## Read more\n\n- [GitLab 18.3: Expanding AI orchestration in software engineering](https://about.gitlab.com/blog/gitlab-18-3-expanding-ai-orchestration-in-software-engineering/)\n- [GitLab Duo Agent Platform Public Beta: Next-gen AI orchestration and more](https://about.gitlab.com/blog/gitlab-duo-agent-platform-public-beta/)\n","content:en-us:blog:how-gitlab-duo-agent-platform-transforms-dataops.yml","yaml","How Gitlab Duo Agent Platform Transforms Dataops","content","en-us/blog/how-gitlab-duo-agent-platform-transforms-dataops.yml","en-us/blog/how-gitlab-duo-agent-platform-transforms-dataops","yml",{"_path":34,"_dir":35,"_draft":6,"_partial":6,"_locale":7,"data":36,"_id":457,"_type":27,"title":458,"_source":29,"_file":459,"_stem":460,"_extension":32},"/shared/en-us/main-navigation","en-us",{"logo":37,"freeTrial":42,"sales":47,"login":52,"items":57,"search":388,"minimal":419,"duo":438,"pricingDeployment":447},{"config":38},{"href":39,"dataGaName":40,"dataGaLocation":41},"/","gitlab logo","header",{"text":43,"config":44},"Get free trial",{"href":45,"dataGaName":46,"dataGaLocation":41},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":48,"config":49},"Talk to sales",{"href":50,"dataGaName":51,"dataGaLocation":41},"/sales/","sales",{"text":53,"config":54},"Sign in",{"href":55,"dataGaName":56,"dataGaLocation":41},"https://gitlab.com/users/sign_in/","sign in",[58,102,199,204,309,369],{"text":59,"config":60,"cards":62,"footer":85},"Platform",{"dataNavLevelOne":61},"platform",[63,69,77],{"title":59,"description":64,"link":65},"The most comprehensive AI-powered DevSecOps Platform",{"text":66,"config":67},"Explore our Platform",{"href":68,"dataGaName":61,"dataGaLocation":41},"/platform/",{"title":70,"description":71,"link":72},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":73,"config":74},"Meet GitLab Duo",{"href":75,"dataGaName":76,"dataGaLocation":41},"/gitlab-duo/","gitlab duo ai",{"title":78,"description":79,"link":80},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":81,"config":82},"Learn more",{"href":83,"dataGaName":84,"dataGaLocation":41},"/why-gitlab/","why gitlab",{"title":86,"items":87},"Get started with",[88,93,98],{"text":89,"config":90},"Platform Engineering",{"href":91,"dataGaName":92,"dataGaLocation":41},"/solutions/platform-engineering/","platform engineering",{"text":94,"config":95},"Developer Experience",{"href":96,"dataGaName":97,"dataGaLocation":41},"/developer-experience/","Developer experience",{"text":99,"config":100},"MLOps",{"href":101,"dataGaName":99,"dataGaLocation":41},"/topics/devops/the-role-of-ai-in-devops/",{"text":103,"left":13,"config":104,"link":106,"lists":110,"footer":181},"Product",{"dataNavLevelOne":105},"solutions",{"text":107,"config":108},"View all Solutions",{"href":109,"dataGaName":105,"dataGaLocation":41},"/solutions/",[111,136,160],{"title":112,"description":113,"link":114,"items":119},"Automation","CI/CD and automation to accelerate deployment",{"config":115},{"icon":116,"href":117,"dataGaName":118,"dataGaLocation":41},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[120,124,128,132],{"text":121,"config":122},"CI/CD",{"href":123,"dataGaLocation":41,"dataGaName":121},"/solutions/continuous-integration/",{"text":125,"config":126},"AI-Assisted Development",{"href":75,"dataGaLocation":41,"dataGaName":127},"AI assisted development",{"text":129,"config":130},"Source Code Management",{"href":131,"dataGaLocation":41,"dataGaName":129},"/solutions/source-code-management/",{"text":133,"config":134},"Automated Software Delivery",{"href":117,"dataGaLocation":41,"dataGaName":135},"Automated software delivery",{"title":137,"description":138,"link":139,"items":144},"Security","Deliver code faster without compromising security",{"config":140},{"href":141,"dataGaName":142,"dataGaLocation":41,"icon":143},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[145,150,155],{"text":146,"config":147},"Application Security Testing",{"href":148,"dataGaName":149,"dataGaLocation":41},"/solutions/application-security-testing/","Application security testing",{"text":151,"config":152},"Software Supply Chain Security",{"href":153,"dataGaLocation":41,"dataGaName":154},"/solutions/supply-chain/","Software supply chain security",{"text":156,"config":157},"Software Compliance",{"href":158,"dataGaName":159,"dataGaLocation":41},"/solutions/software-compliance/","software compliance",{"title":161,"link":162,"items":167},"Measurement",{"config":163},{"icon":164,"href":165,"dataGaName":166,"dataGaLocation":41},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[168,172,176],{"text":169,"config":170},"Visibility & Measurement",{"href":165,"dataGaLocation":41,"dataGaName":171},"Visibility and Measurement",{"text":173,"config":174},"Value Stream Management",{"href":175,"dataGaLocation":41,"dataGaName":173},"/solutions/value-stream-management/",{"text":177,"config":178},"Analytics & Insights",{"href":179,"dataGaLocation":41,"dataGaName":180},"/solutions/analytics-and-insights/","Analytics and insights",{"title":182,"items":183},"GitLab for",[184,189,194],{"text":185,"config":186},"Enterprise",{"href":187,"dataGaLocation":41,"dataGaName":188},"/enterprise/","enterprise",{"text":190,"config":191},"Small Business",{"href":192,"dataGaLocation":41,"dataGaName":193},"/small-business/","small business",{"text":195,"config":196},"Public Sector",{"href":197,"dataGaLocation":41,"dataGaName":198},"/solutions/public-sector/","public sector",{"text":200,"config":201},"Pricing",{"href":202,"dataGaName":203,"dataGaLocation":41,"dataNavLevelOne":203},"/pricing/","pricing",{"text":205,"config":206,"link":208,"lists":212,"feature":296},"Resources",{"dataNavLevelOne":207},"resources",{"text":209,"config":210},"View all resources",{"href":211,"dataGaName":207,"dataGaLocation":41},"/resources/",[213,246,268],{"title":214,"items":215},"Getting started",[216,221,226,231,236,241],{"text":217,"config":218},"Install",{"href":219,"dataGaName":220,"dataGaLocation":41},"/install/","install",{"text":222,"config":223},"Quick start guides",{"href":224,"dataGaName":225,"dataGaLocation":41},"/get-started/","quick setup checklists",{"text":227,"config":228},"Learn",{"href":229,"dataGaLocation":41,"dataGaName":230},"https://university.gitlab.com/","learn",{"text":232,"config":233},"Product documentation",{"href":234,"dataGaName":235,"dataGaLocation":41},"https://docs.gitlab.com/","product documentation",{"text":237,"config":238},"Best practice videos",{"href":239,"dataGaName":240,"dataGaLocation":41},"/getting-started-videos/","best practice videos",{"text":242,"config":243},"Integrations",{"href":244,"dataGaName":245,"dataGaLocation":41},"/integrations/","integrations",{"title":247,"items":248},"Discover",[249,254,258,263],{"text":250,"config":251},"Customer success stories",{"href":252,"dataGaName":253,"dataGaLocation":41},"/customers/","customer success stories",{"text":255,"config":256},"Blog",{"href":257,"dataGaName":5,"dataGaLocation":41},"/blog/",{"text":259,"config":260},"Remote",{"href":261,"dataGaName":262,"dataGaLocation":41},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":264,"config":265},"TeamOps",{"href":266,"dataGaName":267,"dataGaLocation":41},"/teamops/","teamops",{"title":269,"items":270},"Connect",[271,276,281,286,291],{"text":272,"config":273},"GitLab Services",{"href":274,"dataGaName":275,"dataGaLocation":41},"/services/","services",{"text":277,"config":278},"Community",{"href":279,"dataGaName":280,"dataGaLocation":41},"/community/","community",{"text":282,"config":283},"Forum",{"href":284,"dataGaName":285,"dataGaLocation":41},"https://forum.gitlab.com/","forum",{"text":287,"config":288},"Events",{"href":289,"dataGaName":290,"dataGaLocation":41},"/events/","events",{"text":292,"config":293},"Partners",{"href":294,"dataGaName":295,"dataGaLocation":41},"/partners/","partners",{"backgroundColor":297,"textColor":298,"text":299,"image":300,"link":304},"#2f2a6b","#fff","Insights for the future of software development",{"altText":301,"config":302},"the source promo card",{"src":303},"/images/navigation/the-source-promo-card.svg",{"text":305,"config":306},"Read the latest",{"href":307,"dataGaName":308,"dataGaLocation":41},"/the-source/","the source",{"text":310,"config":311,"lists":313},"Company",{"dataNavLevelOne":312},"company",[314],{"items":315},[316,321,327,329,334,339,344,349,354,359,364],{"text":317,"config":318},"About",{"href":319,"dataGaName":320,"dataGaLocation":41},"/company/","about",{"text":322,"config":323,"footerGa":326},"Jobs",{"href":324,"dataGaName":325,"dataGaLocation":41},"/jobs/","jobs",{"dataGaName":325},{"text":287,"config":328},{"href":289,"dataGaName":290,"dataGaLocation":41},{"text":330,"config":331},"Leadership",{"href":332,"dataGaName":333,"dataGaLocation":41},"/company/team/e-group/","leadership",{"text":335,"config":336},"Team",{"href":337,"dataGaName":338,"dataGaLocation":41},"/company/team/","team",{"text":340,"config":341},"Handbook",{"href":342,"dataGaName":343,"dataGaLocation":41},"https://handbook.gitlab.com/","handbook",{"text":345,"config":346},"Investor relations",{"href":347,"dataGaName":348,"dataGaLocation":41},"https://ir.gitlab.com/","investor relations",{"text":350,"config":351},"Trust Center",{"href":352,"dataGaName":353,"dataGaLocation":41},"/security/","trust center",{"text":355,"config":356},"AI Transparency Center",{"href":357,"dataGaName":358,"dataGaLocation":41},"/ai-transparency-center/","ai transparency center",{"text":360,"config":361},"Newsletter",{"href":362,"dataGaName":363,"dataGaLocation":41},"/company/contact/","newsletter",{"text":365,"config":366},"Press",{"href":367,"dataGaName":368,"dataGaLocation":41},"/press/","press",{"text":370,"config":371,"lists":372},"Contact us",{"dataNavLevelOne":312},[373],{"items":374},[375,378,383],{"text":48,"config":376},{"href":50,"dataGaName":377,"dataGaLocation":41},"talk to sales",{"text":379,"config":380},"Get help",{"href":381,"dataGaName":382,"dataGaLocation":41},"/support/","get help",{"text":384,"config":385},"Customer portal",{"href":386,"dataGaName":387,"dataGaLocation":41},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":389,"login":390,"suggestions":397},"Close",{"text":391,"link":392},"To search repositories and projects, login to",{"text":393,"config":394},"gitlab.com",{"href":55,"dataGaName":395,"dataGaLocation":396},"search login","search",{"text":398,"default":399},"Suggestions",[400,402,406,408,412,416],{"text":70,"config":401},{"href":75,"dataGaName":70,"dataGaLocation":396},{"text":403,"config":404},"Code Suggestions (AI)",{"href":405,"dataGaName":403,"dataGaLocation":396},"/solutions/code-suggestions/",{"text":121,"config":407},{"href":123,"dataGaName":121,"dataGaLocation":396},{"text":409,"config":410},"GitLab on AWS",{"href":411,"dataGaName":409,"dataGaLocation":396},"/partners/technology-partners/aws/",{"text":413,"config":414},"GitLab on Google Cloud",{"href":415,"dataGaName":413,"dataGaLocation":396},"/partners/technology-partners/google-cloud-platform/",{"text":417,"config":418},"Why GitLab?",{"href":83,"dataGaName":417,"dataGaLocation":396},{"freeTrial":420,"mobileIcon":425,"desktopIcon":430,"secondaryButton":433},{"text":421,"config":422},"Start free trial",{"href":423,"dataGaName":46,"dataGaLocation":424},"https://gitlab.com/-/trials/new/","nav",{"altText":426,"config":427},"Gitlab Icon",{"src":428,"dataGaName":429,"dataGaLocation":424},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":426,"config":431},{"src":432,"dataGaName":429,"dataGaLocation":424},"/images/brand/gitlab-logo-type.svg",{"text":434,"config":435},"Get Started",{"href":436,"dataGaName":437,"dataGaLocation":424},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":439,"mobileIcon":443,"desktopIcon":445},{"text":440,"config":441},"Learn more about GitLab Duo",{"href":75,"dataGaName":442,"dataGaLocation":424},"gitlab duo",{"altText":426,"config":444},{"src":428,"dataGaName":429,"dataGaLocation":424},{"altText":426,"config":446},{"src":432,"dataGaName":429,"dataGaLocation":424},{"freeTrial":448,"mobileIcon":453,"desktopIcon":455},{"text":449,"config":450},"Back to pricing",{"href":202,"dataGaName":451,"dataGaLocation":424,"icon":452},"back to pricing","GoBack",{"altText":426,"config":454},{"src":428,"dataGaName":429,"dataGaLocation":424},{"altText":426,"config":456},{"src":432,"dataGaName":429,"dataGaLocation":424},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":462,"_dir":35,"_draft":6,"_partial":6,"_locale":7,"title":463,"button":464,"image":469,"config":473,"_id":475,"_type":27,"_source":29,"_file":476,"_stem":477,"_extension":32},"/shared/en-us/banner","is now in public beta!",{"text":465,"config":466},"Try the Beta",{"href":467,"dataGaName":468,"dataGaLocation":41},"/gitlab-duo/agent-platform/","duo banner",{"altText":470,"config":471},"GitLab Duo Agent Platform",{"src":472},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":474},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":479,"_dir":35,"_draft":6,"_partial":6,"_locale":7,"data":480,"_id":684,"_type":27,"title":685,"_source":29,"_file":686,"_stem":687,"_extension":32},"/shared/en-us/main-footer",{"text":481,"source":482,"edit":488,"contribute":493,"config":498,"items":503,"minimal":676},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":483,"config":484},"View page source",{"href":485,"dataGaName":486,"dataGaLocation":487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":489,"config":490},"Edit this page",{"href":491,"dataGaName":492,"dataGaLocation":487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":494,"config":495},"Please contribute",{"href":496,"dataGaName":497,"dataGaLocation":487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":499,"facebook":500,"youtube":501,"linkedin":502},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[504,527,583,612,646],{"title":59,"links":505,"subMenu":510},[506],{"text":507,"config":508},"DevSecOps platform",{"href":68,"dataGaName":509,"dataGaLocation":487},"devsecops platform",[511],{"title":200,"links":512},[513,517,522],{"text":514,"config":515},"View plans",{"href":202,"dataGaName":516,"dataGaLocation":487},"view plans",{"text":518,"config":519},"Why Premium?",{"href":520,"dataGaName":521,"dataGaLocation":487},"/pricing/premium/","why premium",{"text":523,"config":524},"Why Ultimate?",{"href":525,"dataGaName":526,"dataGaLocation":487},"/pricing/ultimate/","why ultimate",{"title":528,"links":529},"Solutions",[530,535,537,539,544,549,553,556,560,565,567,570,573,578],{"text":531,"config":532},"Digital transformation",{"href":533,"dataGaName":534,"dataGaLocation":487},"/topics/digital-transformation/","digital transformation",{"text":146,"config":536},{"href":148,"dataGaName":146,"dataGaLocation":487},{"text":135,"config":538},{"href":117,"dataGaName":118,"dataGaLocation":487},{"text":540,"config":541},"Agile development",{"href":542,"dataGaName":543,"dataGaLocation":487},"/solutions/agile-delivery/","agile delivery",{"text":545,"config":546},"Cloud transformation",{"href":547,"dataGaName":548,"dataGaLocation":487},"/topics/cloud-native/","cloud transformation",{"text":550,"config":551},"SCM",{"href":131,"dataGaName":552,"dataGaLocation":487},"source code management",{"text":121,"config":554},{"href":123,"dataGaName":555,"dataGaLocation":487},"continuous integration & delivery",{"text":557,"config":558},"Value stream management",{"href":175,"dataGaName":559,"dataGaLocation":487},"value stream management",{"text":561,"config":562},"GitOps",{"href":563,"dataGaName":564,"dataGaLocation":487},"/solutions/gitops/","gitops",{"text":185,"config":566},{"href":187,"dataGaName":188,"dataGaLocation":487},{"text":568,"config":569},"Small business",{"href":192,"dataGaName":193,"dataGaLocation":487},{"text":571,"config":572},"Public sector",{"href":197,"dataGaName":198,"dataGaLocation":487},{"text":574,"config":575},"Education",{"href":576,"dataGaName":577,"dataGaLocation":487},"/solutions/education/","education",{"text":579,"config":580},"Financial services",{"href":581,"dataGaName":582,"dataGaLocation":487},"/solutions/finance/","financial services",{"title":205,"links":584},[585,587,589,591,594,596,598,600,602,604,606,608,610],{"text":217,"config":586},{"href":219,"dataGaName":220,"dataGaLocation":487},{"text":222,"config":588},{"href":224,"dataGaName":225,"dataGaLocation":487},{"text":227,"config":590},{"href":229,"dataGaName":230,"dataGaLocation":487},{"text":232,"config":592},{"href":234,"dataGaName":593,"dataGaLocation":487},"docs",{"text":255,"config":595},{"href":257,"dataGaName":5,"dataGaLocation":487},{"text":250,"config":597},{"href":252,"dataGaName":253,"dataGaLocation":487},{"text":259,"config":599},{"href":261,"dataGaName":262,"dataGaLocation":487},{"text":272,"config":601},{"href":274,"dataGaName":275,"dataGaLocation":487},{"text":264,"config":603},{"href":266,"dataGaName":267,"dataGaLocation":487},{"text":277,"config":605},{"href":279,"dataGaName":280,"dataGaLocation":487},{"text":282,"config":607},{"href":284,"dataGaName":285,"dataGaLocation":487},{"text":287,"config":609},{"href":289,"dataGaName":290,"dataGaLocation":487},{"text":292,"config":611},{"href":294,"dataGaName":295,"dataGaLocation":487},{"title":310,"links":613},[614,616,618,620,622,624,626,630,635,637,639,641],{"text":317,"config":615},{"href":319,"dataGaName":312,"dataGaLocation":487},{"text":322,"config":617},{"href":324,"dataGaName":325,"dataGaLocation":487},{"text":330,"config":619},{"href":332,"dataGaName":333,"dataGaLocation":487},{"text":335,"config":621},{"href":337,"dataGaName":338,"dataGaLocation":487},{"text":340,"config":623},{"href":342,"dataGaName":343,"dataGaLocation":487},{"text":345,"config":625},{"href":347,"dataGaName":348,"dataGaLocation":487},{"text":627,"config":628},"Sustainability",{"href":629,"dataGaName":627,"dataGaLocation":487},"/sustainability/",{"text":631,"config":632},"Diversity, inclusion and belonging (DIB)",{"href":633,"dataGaName":634,"dataGaLocation":487},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":350,"config":636},{"href":352,"dataGaName":353,"dataGaLocation":487},{"text":360,"config":638},{"href":362,"dataGaName":363,"dataGaLocation":487},{"text":365,"config":640},{"href":367,"dataGaName":368,"dataGaLocation":487},{"text":642,"config":643},"Modern Slavery Transparency Statement",{"href":644,"dataGaName":645,"dataGaLocation":487},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":647,"links":648},"Contact Us",[649,652,654,656,661,666,671],{"text":650,"config":651},"Contact an expert",{"href":50,"dataGaName":51,"dataGaLocation":487},{"text":379,"config":653},{"href":381,"dataGaName":382,"dataGaLocation":487},{"text":384,"config":655},{"href":386,"dataGaName":387,"dataGaLocation":487},{"text":657,"config":658},"Status",{"href":659,"dataGaName":660,"dataGaLocation":487},"https://status.gitlab.com/","status",{"text":662,"config":663},"Terms of use",{"href":664,"dataGaName":665,"dataGaLocation":487},"/terms/","terms of use",{"text":667,"config":668},"Privacy statement",{"href":669,"dataGaName":670,"dataGaLocation":487},"/privacy/","privacy statement",{"text":672,"config":673},"Cookie preferences",{"dataGaName":674,"dataGaLocation":487,"id":675,"isOneTrustButton":13},"cookie preferences","ot-sdk-btn",{"items":677},[678,680,682],{"text":662,"config":679},{"href":664,"dataGaName":665,"dataGaLocation":487},{"text":667,"config":681},{"href":669,"dataGaName":670,"dataGaLocation":487},{"text":672,"config":683},{"dataGaName":674,"dataGaLocation":487,"id":675,"isOneTrustButton":13},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[689],{"_path":690,"_dir":691,"_draft":6,"_partial":6,"_locale":7,"content":692,"config":695,"_id":698,"_type":27,"title":699,"_source":29,"_file":700,"_stem":701,"_extension":32},"/en-us/blog/authors/dennis-van-rooijen","authors",{"name":17,"config":693},{"headshot":694},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758031391/muvwg1sxetzekmuhqdql.png",{"template":696,"gitlabHandle":697},"BlogAuthor","dvanrooijen2","content:en-us:blog:authors:dennis-van-rooijen.yml","Dennis Van Rooijen","en-us/blog/authors/dennis-van-rooijen.yml","en-us/blog/authors/dennis-van-rooijen",{"_path":703,"_dir":35,"_draft":6,"_partial":6,"_locale":7,"header":704,"eyebrow":705,"blurb":706,"button":707,"secondaryButton":711,"_id":713,"_type":27,"title":714,"_source":29,"_file":715,"_stem":716,"_extension":32},"/shared/en-us/next-steps","Start shipping better software faster","50%+ of the Fortune 100 trust GitLab","See what your team can do with the intelligent\n\n\nDevSecOps platform.\n",{"text":43,"config":708},{"href":709,"dataGaName":46,"dataGaLocation":710},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":48,"config":712},{"href":50,"dataGaName":51,"dataGaLocation":710},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1758521523266]