CoolFace
Datasetpublic

Helmcode/stack-v3-devops

The Stack v3 DevOps Corpus 13,234,862 complete infrastructure units extracted from The Stack v3, grouped into seven classes and gated on content rather than popularity. A unit is not a file, it is the thing an engineer would actually run: a Helm chart arrives with its Chart.yaml, values.yaml and every template; a Terraform module with all of its .tf files; an Ansible role with its tasks, defaults and handlers. That is only possible because The Stack v3 groups rows by repository… See the full description on the dataset page: https://huggingface.co/datasets/Helmcode/stack-v3-devops.

sourceHugging Faceodc-byupdated 2mo agoView on Hugging Face
5likes1.2kdownloads
README.md357 linesDownload Raw Back to root
1---2license: odc-by3pretty_name: The Stack v3 DevOps Corpus4size_categories:5  - 10M<n<100M6task_categories:7  - text-generation8language:9  - code10tags:11  - infrastructure-as-code12  - devops13  - kubernetes14  - helm15  - terraform16  - ansible17  - docker18  - github-actions19  - sre20configs:21  - config_name: helm_chart22    data_files:23      - split: train24        path: data/helm_chart/train-*.parquet25  - config_name: terraform_module26    data_files:27      - split: train28        path: data/terraform_module/train-*.parquet29  - config_name: manifest_set30    data_files:31      - split: train32        path: data/manifest_set/train-*.parquet33  - config_name: ansible_role34    data_files:35      - split: train36        path: data/ansible_role/train-*.parquet37  - config_name: dockerfile38    data_files:39      - split: train40        path: data/dockerfile/train-*.parquet41  - config_name: workflow42    data_files:43      - split: train44        path: data/workflow/train-*.parquet45  - config_name: compose46    data_files:47      - split: train48        path: data/compose/train-*.parquet49---50 51# The Stack v3 DevOps Corpus52 5313,234,862 complete infrastructure units extracted from54[The Stack v3](https://huggingface.co/datasets/HuggingFaceCode/stack-v3-train),55grouped into seven classes and gated on content rather than popularity.56 57A unit is not a file, it is the thing an engineer would actually run: a Helm chart58arrives with its `Chart.yaml`, `values.yaml` and every template; a Terraform module59with all of its `.tf` files; an Ansible role with its tasks, defaults and handlers.60That is only possible because The Stack v3 groups rows by repository, which v2 did61not.62 63## Why this exists64 65Language detection cannot find infrastructure code. Helm templates, Kubernetes66manifests, Ansible playbooks, CI pipelines and Prometheus rules are all just67`YAML` to `go-enry`, and **59.6% of the YAML in the corpus is not infrastructure68at all** (Spring config, i18n plurals, Drupal exports, dbt models, Conda69environments). Path heuristics do not fix it either: a directory-name rule finds70only **33% of real Kubernetes manifests** and is **57% precise**.71 72So classification here is content-first. Every YAML unit was parsed and inspected,73and the resulting labels were scored against an independent YAML parser rather74than against more regexes:75 76| Class | Precision | Recall |77|---|---|---|78| kubernetes | 97.8% | 97.2% |79| github_actions | 98.9% | 100.0% |80| compose | 97.2% | 99.3% |81| helm | 93.9% (structural) | not measurable, templates are not valid YAML |82| ansible | 86.4% | 90.3% |83| terraform | 98.9% (extension-anchored) | |84| dockerfile | 99.7% (extension-anchored) | |85 86Roughly half of all Helm and Ansible labels come from repository context alone:87a `values.yaml` or a `defaults/main.yml` is a bare tree of variables, and no88amount of content inspection can tell you what it belongs to.89 90## Configs91 92| Config | Units | Parquet | What a unit is |93|---|---|---|---|94| `helm_chart` | 65,422 | 0.15 GB | Complete charts: `Chart.yaml` plus templates, and `values.yaml` where present |95| `terraform_module` | 779,730 | 1.06 GB | Directories with two or more `.tf` files declaring real blocks |96| `manifest_set` | 743,191 | 0.42 GB | Directories of two or more Kubernetes manifests that parse |97| `ansible_role` | 444,411 | 0.34 GB | Roles with a verifiable task list, plus defaults, handlers and templates |98| `dockerfile` | 4,609,451 | 1.14 GB | Single files containing real Dockerfile instructions |99| `workflow` | 3,380,313 | 1.41 GB | GitHub Actions workflows with triggers and jobs |100| `compose` | 3,212,344 | 0.87 GB | Docker Compose files with a services mapping |101| **total** | **13,234,862** | **5.40 GB** | |102 103### What is inside each one104 105- **`helm_chart`** the scarcest and richest class. `Chart.yaml`, `values.yaml`106  where present, every template and helper. Median 4 templates, up to 56.107- **`terraform_module`** a directory of two or more `.tf` files that declare real108  resources, modules, variables or outputs. Median 3 files. 70.7% declare109  variables, 47.8% outputs.110- **`manifest_set`** a directory of two or more Kubernetes manifests that parse.111  Median 3. Most common kinds: Deployment, Service, Kustomization, ConfigMap,112  Ingress, PersistentVolumeClaim, Secret.113- **`ansible_role`** `tasks/`, and whichever of `defaults/`, `handlers/`, `vars/`,114  `meta/`, `templates/`, `files/` the role ships. 24.6% carry defaults.115- **`dockerfile`** one file with real instructions. Median 8 instructions,116  20.3% multi-stage.117- **`workflow`** one GitHub Actions workflow with triggers and jobs. Median 1 job118  and 5 steps.119- **`compose`** one Compose file with a services mapping. Median 2 services.120 121### Using it122 123```python124from datasets import load_dataset125 126charts = load_dataset("Helmcode/stack-v3-devops", "helm_chart", split="train")127```128 129Charts that render standalone, which is what an executable benchmark needs:130 131```python132renderable = charts.filter(lambda row: row["flags"]["self_contained"])133```134 135Stream the large configs instead of downloading them:136 137```python138dockerfiles = load_dataset(139    "Helmcode/stack-v3-devops", "dockerfile", split="train", streaming=True140)141hardened = (row for row in dockerfiles if row["flags"]["pins_digest"])142```143 144Reconstruct a unit as files on disk, which is how you feed it to `helm lint`,145`terraform validate` or `hadolint`:146 147```python148import pathlib149 150def materialise(row, root):151    prefix = row["unit_prefix"]152    for entry in row["files"]:153        relative = entry["path"][len(prefix):].lstrip("/") if prefix else entry["path"]154        target = pathlib.Path(root, relative or pathlib.Path(entry["path"]).name)155        target.parent.mkdir(parents=True, exist_ok=True)156        target.write_text(entry["content"])157 158materialise(charts[0], "/tmp/chart")159```160 161Restrict to units whose every file carries a permissive license header, but read162the licensing section first, because that is not the same as permissively163licensed code:164 165```python166permissive = charts.filter(lambda row: row["flags"]["all_permissive"])167```168 169### What it is good for170 171- **Evaluation.** Complete, self-contained units are what an executable benchmark172  needs: render the chart, validate the module, lint the Dockerfile, and score on173  whether real tools accept the output.174- **Fine-tuning on infrastructure tasks**, where the unit boundary matters more175  than the file: a model that writes one template without `values.yaml` has not176  written a chart.177- **Measuring practice.** The flags make questions like "what share of public178  Dockerfiles run as root" answerable in one pass instead of a research project.179 180It is **not** a pretraining corpus. 5.4 GB is small, and the classes are181deliberately unbalanced towards what exists rather than what would balance nicely.182 183## Schema184 185Every config shares a base schema and adds its own `quality` and `flags` structs.186 187| Field | Type | Notes |188|---|---|---|189| `unit_type` | string | one of the seven config names |190| `repo_path` | string | `owner/name`, for attribution |191| `commit_id` | string | the exact commit the files came from |192| `stars` | int32 | GitHub stars at crawl time |193| `unit_prefix` | string | directory the unit was rooted at, `""` for repo root |194| `shard` | int32 | source shard, for reproducibility |195| `license_types` | list\<string\> | distinct `license_type` values across the unit's files |196| `files` | list\<struct\> | `path`, `content`, `license_type`, `detected_licenses`, `size_bytes` |197| `quality` | struct | per class: template counts, stage counts, service counts, manifest kinds |198| `flags` | struct | derived booleans, below |199 200Flags worth knowing about:201 202- `self_contained` (helm_chart): the chart does not call a helper it lacks.203  **72.9%** of charts qualify; the rest cannot be rendered204  by `helm template` on their own.205- `pins_digest` / `uses_latest_tag` (dockerfile): supply-chain hygiene.206- `has_unpinned_action` (workflow): actions referenced by tag or branch instead of207  a commit SHA.208- `all_permissive`: every file in the unit is labelled `permissive`. Read the209  licensing section before relying on this.210 211## What this corpus says about real-world infrastructure212 213Measured across every unit, not a sample:214 215- **89.0% of Dockerfiles set no `USER`**, so the container runs as root216- **98.6% of Dockerfiles declare no `HEALTHCHECK`**217- **89.5% of workflows declare no `permissions`**, inheriting the default token scope218- **91.1% of Compose files define no healthcheck**219- 20.3% of Dockerfiles are multi-stage220- Top Kubernetes kinds: Deployment, Service, Kustomization, ConfigMap, Ingress221 222That is the baseline any model trained on public infrastructure code will imitate,223which is the point of publishing it as a measurable corpus rather than a curated224showcase.225 226## Provenance and how it was built227 228Built with [helmcode/stack-slice](https://github.com/helmcode/stack-slice)229(Apache-2.0). The corpus was surveyed and extracted **without downloading the2304.71 TB dataset**: `content` is 96.9% of every shard, so a metadata-only pass231costs 1% of the bytes, and extraction streams shards over HTTP range requests232without ever storing one.233 234- Source revision: **`de81e3ca7151`** of `HuggingFaceCode/stack-v3-train`235- Shards swept: **8,196 of 8,196**, covering 157.9M repositories236- Forks skipped, so units come from the repository that authored them237- Re-filtered for opt-out on **2026-07-28**, against the revision then at238  HEAD (`d7bc7991ea32`), and verified equivalent to the current HEAD239  `2b4797afd567` (see Licensing)240 241Gates are content-based, never popularity-based: a chart must have parseable242metadata, two or more templates and actual templating; a Terraform module must243declare real blocks and not be machine-generated; an Ansible role must have a task244list a parser accepts; a manifest set must have two or more manifests that load.245 246## Licensing, and a finding you should not skip247 248This dataset is released under **ODC-By 1.0**, inherited from The Stack v3.249**The code inside remains under its original licenses**, and `repo_path` plus250`commit_id` are included on every unit precisely so attribution is possible.251 252**The `license_type` labels are header-based, not repository-based.** In the source253corpus only 3.41% of files are labelled `permissive` and 98.2% of repositories254contain none at all. Apache-2.0 is detected 26,624 times against MIT's 442, which255inverts their real popularity on GitHub: the Apache convention puts a license256header in every source file, while MIT projects ship a single root `LICENSE`. So257`license_type == permissive` means **"this file carries an inline license header"**,258not "this file comes from a permissively licensed project".259 260Two consequences:261 2621. Filtering to `permissive` does not give you a representative permissive263   corpus, it gives you an Apache-2.0-skewed slice.2642. The remaining `no_license` majority is code with **no license grant at all**,265   not code that is permissively licensed. Treat it accordingly.266 267The repository-level license cannot be recovered from within The Stack v3 either:268plain-text `LICENSE` files were dropped by its quality filter, so only 8 of 20,923269repositories in a sample shard ship one. A provably permissive subset needs270external enrichment keyed on `repo_path`.271 272**Opt-out.** Upstream applies opt-out removals in place and re-uploads. This273dataset was re-filtered by `repo_path` on 2026-07-28, dropping2749,439 units whose repositories had been removed.275 276Be aware that **upstream rewrites its own history**: the revision we filtered277against (`d7bc7991ea32`) was squashed away within a day, so source SHAs are278not durable references. We therefore record the filter date alongside the SHA, and279re-verify against the current HEAD (`2b4797afd567`) rather than assuming an280old SHA still resolves. If you find your code281here, check inclusion in the source corpus with the282[Am I in The Stack?](https://huggingface.co/spaces/HuggingFaceCode/in-the-stack)283Space and submit a removal request following the284[opt-out instructions](https://github.com/bigcode-project/opt-out-v2); we285re-filter on each upstream patch release.286 287## Known limitations288 289- **The source corpus repeats file rows inside a repository**: 10.4% of290  repositories and 14.5% of all file rows, byte-identical by `content_id`. This291  dataset deduplicates by (path, content), removing 2,166,221 repeated292  files, and then **drops the 122,886 units that only met their293  gate because of that repetition** (a "set of two manifests" whose two manifests294  were the same file is not a set of two). Counts here are therefore lower than a295  naive extraction would report, and correctly so. Quality counters such as296  `templates`, `tf_files` and `manifests` are recomputed after deduplication, so297  they describe the files actually present.298- **27.1% of Helm charts cannot render standalone**299  because they call helpers they do not carry. Filter on `self_contained`.300- **Ansible precision is a floor, not a measurement.** "A list of mappings with301  Ansible-ish keys" also matches ordinary YAML lists, and role variable files are302  indistinguishable from any other mapping by content alone.303- `manifest_set` groups manifests by directory, which is a convention, not a304  deployment boundary.305- Stars are as of the crawl and 58-76% of units come from repositories with none.306  Popularity was deliberately not used as a gate; see the card's reasoning above.307 308## Updates and versioning309 310Upstream applies opt-out removals in place, re-uploads the whole dataset and311squashes its history, which means the source moves and old revision SHAs stop312resolving. This dataset therefore records both the revision it was313extracted from and the revision it was last compliance-filtered against, and both314appear above. When upstream ships a patch release we re-filter and push a new315version; the extraction itself is not repeated unless the tooling changes.316 317If you need byte-for-byte reproducibility, pin the dataset revision you loaded.318 319## Reproducing this dataset320 321Everything here was produced by [helmcode/stack-slice](https://github.com/helmcode/stack-slice):322 323```bash324# Survey the corpus for 179 MB of transfer, no download325python -m stackslice.scan --shards 24326 327# Score the classifier against an independent YAML parser328python -m stackslice.measure --shards 3329 330# Sweep and extract units (streams shards, stores nothing but output)331python -m stackslice.extract --shards 8196 --workers 12 --out units332 333# Re-filter for opt-out, deduplicate, add flags334python -m stackslice.finalize units --out units_final \335    --revision <target-revision> --uuid <shard-uuid>336 337# Convert to parquet, one config per class338python -m stackslice.publish units_final --out dataset339```340 341The full measurement record, including the findings quoted in this card, is in342[FINDINGS.md](https://github.com/helmcode/stack-slice/blob/main/FINDINGS.md).343 344## Citation345 346```bibtex347@misc{stack_v3_devops,348  title  = {The Stack v3 DevOps Corpus},349  author = {Helmcode},350  year   = {2026},351  url    = {https://huggingface.co/datasets/Helmcode/stack-v3-devops},352  note   = {Extracted from The Stack v3 with helmcode/stack-slice}353}354```355 356Please also cite the source corpus, [The Stack v3](https://huggingface.co/datasets/HuggingFaceCode/stack-v3-train).357