Repository navigation
feat(component-browser): insert components into the include list - #346
Merged
eFAILution merged 2 commits intoOct 13, 2026
Merged
eFAILution merged 2 commits into
eFAILution merged 2 commits into
Conversation
eFAILution
reviewed
Oct 13, 2026
eFAILution
left a comment
Owner
There was a problem hiding this comment.
Tried a bunch of layouts against this and it held up well. One small bug inline. The bundle growth is a bit much for one feature, but I don't see a clean way to get ranges out of js-yaml, so I'm OK with it.
| } | ||
|
|
||
| const keyLine = source.lineOf(keyRange[0]); | ||
| if (isScalar(value) && value.value === null && value.source === '') { |
Owner
There was a problem hiding this comment.
include: ~ and include: null come out as a list with - ~ as the first entry, which GitLab will reject. The empty check only matches value.source === ''. Could we treat any null scalar the same way?
X-Guardian
force-pushed
the
feature/insert-component-into-include-list
branch
from
October 13, 2026 08:00
76e5607 to
a058e5a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
- component:snippet at the cursor, wherever that happened to be — often inside a job'sscript:or between two unrelated keys, leaving invalid YAML for the user to cut and paste.include:list, or in a newinclude:block at the top of the file when there isn't one.Change Type
Context
User-facing impact
Existing list → appended after the last entry, including a multi-line last entry (
inputs:,rules:), and indented to match the list (column 0, 2 or 4 spaces). Comments and blank lines trailing the list stay below the new entry.Single
include:entry → converted into a list of the existing entry followed by the new one. Entries are kept verbatim:include: a.ymlinclude:- a.yml- component: …include: { local: a.yml }include:- { local: a.yml }- component: …include: [a.yml, { local: b.yml }]include:- a.yml- { local: b.yml }- component: …include: [a.yml,b.yml]include:- a.yml- b.yml- component: …include: a.yml # sharedinclude: # shared- a.yml- component: …include:local: a.ymlrules: …include:- local: a.ymlrules: …- component: …No
include:→ a newinclude:block above the first line of YAML, so a file's header comments stay on top, followed by a blank line. In a component template, it goes after thespec:header and its---so the include lands in the pipeline document rather than the header.The editor scrolls to the inserted entry if it's off screen.
When it still inserts at the cursor
Some files can't be rewritten without changing behaviour elsewhere or reflowing the user's text. These keep the old cursor insertion:
include: *shared(alias)- *sharednests a list in a list, which GitLab rejects.include: &shared [a.yml](anchor)*sharedis used; dropping it breaks those uses.include: !reference [.defaults, include](tag)include: |(block scalar)include:.[{ local: a.yml,↵rules: [] }], or a wrapped plain scalar)-would need its continuation lines re-indented, i.e. reflowing the user's text. A flow sequence spanning lines is fine as long as each element sits on one line.spec:header with no---GitLab scope
Affected areas
insertComponent)What changed by bucket
src/providers/componentInsertionPoint.ts(new)planComponentInsertion(text, snippet)returns a replace range plus text, ornullfor the forms above. Novscodetypes, followingcomponentBrowserEdit.ts, so the unit suite drives it directly. Theyamlparser locates theinclude:value and tells its kind apart (block or flow, alias, anchor, tag, block scalar), and handles multi-document templates. It's used for source ranges only: the edit is a text splice, so the rest of the file keeps its formatting, quoting and comments. Rendering a modified AST back out would reflow the whole file.package.json,package-lock.json,.ai/context.yamlyaml^2.9.1.js-yaml(used everywhere else) parses to plain values and exposes no source positions. IndevDependenciesalongsidejs-yamlandpreact, since esbuild bundles it. The productionout/extension.jsgrows from 290,484 to 405,121 bytes (+114,637, about 39%).src/providers/componentBrowserProvider.tsinsertComponentreplaces the planned range instead of inserting atselection.active, falling back to the cursor onnull. A replace rather than an insert because converting a single entry rewrites theinclude:line. The edit is nowawaited before the success message, and the inserted lines are revealed. The edit-existing-component flow is unchanged: it still replaces the component in place.Validation
Local checks
npm run compilenpm test(558 passing, 33 new), after a cleannpm cinpm run lintnpm run test:extension-hostTests
tests/unit/componentInsertionPoint.test.tsapplies each plan to the source text and asserts on the resulting document:include:keeps its comment; CRLF column positions; a job-levelinclude:is ignored.#inside quotes isn't a comment), a flow mapping with nested brackets, a flow sequence with a quoted comma, an empty[], a trailing comment, a flow sequence spanning lines, a block mapping with nested lines;nullfor alias, anchor, tag, block scalar, a multi-line flow element and a wrapped plain scalar.nullfor YAML that doesn't parse and for aspec:header with no---; a!referencetag elsewhere in the file doesn't block placement.include:— top of file; after leading comments; comment-only files with and without a trailing newline; empty file; after a template'sspec:header; a template's empty pipeline document; appending to a list in a template's pipeline document.Breaking Changes
Users who relied on cursor placement now get the component in the
include:list instead. The cursor is still used for the forms listed above.Screenshots / Recordings (if UI behavior changed)
- component: …at the cursor, e.g. inside a job.include:list, or createsinclude:at the top of the file.Risk and Rollback
null, so the worst case is the old cursor behaviour rather than a corrupted file; every change is a single undoable edit. (2) Bundle size, +114,637 bytes for the new parser. (3) Two YAML parsers in the codebase;yamlis only used here.Release Notes Draft
include:list (creating one at the top of the file if needed) instead of at the cursor.Checklist