Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 192ab3198b | |||
| f197c368d3 | |||
| d6afb148ca | |||
| 522c637b75 |
@@ -0,0 +1,66 @@
|
||||
# .glint.yml — glint project configuration
|
||||
#
|
||||
# Place this file anywhere between your .gitlab-ci.yml and the repository root.
|
||||
# glint searches upward from the pipeline file and stops at the first .git
|
||||
# boundary, so the repo root is the typical location.
|
||||
#
|
||||
# All keys are optional. Omit or comment out anything you don't need.
|
||||
|
||||
# ── Rule suppression ──────────────────────────────────────────────────────────
|
||||
#
|
||||
# Suppress rules globally for this project. Suppressed rules produce no output
|
||||
# and do not affect the exit code.
|
||||
#
|
||||
ignore:
|
||||
- GL007 # only:/except: used (migrating from legacy syntax)
|
||||
- GL032 # rules:if: references undeclared variable (injected at runtime)
|
||||
|
||||
# ── Severity overrides ────────────────────────────────────────────────────────
|
||||
#
|
||||
# Override the default severity of any rule.
|
||||
# Valid values: error | warning | ignore
|
||||
# "ignore" is equivalent to listing the rule in `ignore:` above.
|
||||
#
|
||||
severity:
|
||||
GL004: warning # demote "unknown stage" to warning during a stage migration
|
||||
GL035: error # promote absolute-path warning to a hard error
|
||||
GL007: ignore # equivalent to adding GL007 to ignore:
|
||||
|
||||
# ── Extra stage names ─────────────────────────────────────────────────────────
|
||||
#
|
||||
# Declare stage names that are valid for this project beyond what is listed in
|
||||
# the pipeline's own `stages:` block. Jobs referencing these stages will not
|
||||
# be flagged by GL004. Useful when stages are defined in a shared parent
|
||||
# template that glint cannot reach.
|
||||
#
|
||||
stages:
|
||||
- quality
|
||||
- security
|
||||
- compliance
|
||||
|
||||
# ── GitLab token ──────────────────────────────────────────────────────────────
|
||||
#
|
||||
# Default personal access token (read_api scope) used to fetch `include:
|
||||
# project:` templates. This is the lowest-priority token source; it is
|
||||
# overridden by the --token flag and the GITLAB_TOKEN / CI_JOB_TOKEN /
|
||||
# GITLAB_PRIVATE_TOKEN environment variables.
|
||||
#
|
||||
# Avoid committing real tokens — use environment variables instead.
|
||||
#
|
||||
# token: glpat-xxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
# ── GitLab instance URL ───────────────────────────────────────────────────────
|
||||
#
|
||||
# Default GitLab instance URL, used when fetching project: and component:
|
||||
# includes. Overridden by --gitlab-url, CI_SERVER_URL, and GITLAB_URL.
|
||||
#
|
||||
# url: https://gitlab.example.com
|
||||
|
||||
# ── Include cache directory ───────────────────────────────────────────────────
|
||||
#
|
||||
# Default directory for caching fetched remote includes (project: and
|
||||
# component:). The directory is created on first use. Overridden by
|
||||
# --cache-dir. When --offline is given without --cache-dir, glint defaults
|
||||
# to ~/.cache/glint regardless of this setting.
|
||||
#
|
||||
# cache_dir: ~/.cache/glint
|
||||
@@ -0,0 +1,11 @@
|
||||
- id: glint
|
||||
name: glint — validate GitLab CI pipeline
|
||||
description: >-
|
||||
Lint .gitlab-ci.yml with glint before committing. Catches misconfigured
|
||||
stages, invalid keywords, broken needs: graphs, deprecated patterns, and
|
||||
more — without a GitLab server.
|
||||
entry: glint check
|
||||
language: golang
|
||||
files: '(^|/)\.gitlab-ci\.yml$'
|
||||
pass_filenames: true
|
||||
minimum_pre_commit_version: '3.0.0'
|
||||
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
This project uses [Semantic Versioning](https://semver.org).
|
||||
|
||||
## [0.2.28] - 2026-06-26
|
||||
|
||||
### Added
|
||||
|
||||
- **Pre-commit hook** — `.pre-commit-hooks.yaml` defines a `glint` hook with `language: golang`; pre-commit builds glint from source automatically on first run and re-runs `glint check` on any staged `.gitlab-ci.yml` changes. Reference: `repo: https://git.k3nny.fr/k3nny/glint, rev: v0.2.28`.
|
||||
|
||||
- **GitLab CI component** (`templates/check.yml`) — a GitLab CI/CD Catalog–compatible component that downloads the glint Linux binary and runs `glint check` as a pipeline job. Accepts inputs: `stage` (default `validate`), `pipeline_file` (default `.gitlab-ci.yml`), `version` (default `latest`), `allow_failure` (default `false`), and `extra_args`. Can also be used as a plain local or remote include without the Catalog.
|
||||
|
||||
- **GitHub Actions composite action** (`action.yml`) — downloads the glint Linux binary into `$RUNNER_TEMP`, adds it to `$GITHUB_PATH`, and runs `glint check`. Inputs: `version`, `file`, `args`. Mirror this repository to GitHub as `k3nny/glint` to reference it as `uses: k3nny/glint@v0.2.28`.
|
||||
|
||||
## [0.2.27] - 2026-06-25
|
||||
|
||||
### Added
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<p align="center">
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License"></a>
|
||||
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/release-v0.2.27-blue.svg" alt="Release"></a>
|
||||
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/release-v0.2.28-blue.svg" alt="Release"></a>
|
||||
</p>
|
||||
|
||||
> **Disclaimer:** This tool was built through iterative AI-assisted development with [Claude](https://claude.ai). It is experimental, incomplete, and not intended for production use. Coverage of GitLab CI keywords is best-effort and may lag behind GitLab's evolving spec. Use it at your own discretion — no correctness guarantees are made. Contributions and bug reports are welcome.
|
||||
@@ -32,7 +32,7 @@ See [FEATURES.md](FEATURES.md) for the complete feature reference and lint rules
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
git clone https://git.k3nny.fr/glint
|
||||
git clone https://git.k3nny.fr/k3nny/glint
|
||||
cd glint
|
||||
go build -o glint ./cmd/glint/...
|
||||
```
|
||||
@@ -58,6 +58,54 @@ Run `glint <command> --help` for all flags. See [USAGE.md](USAGE.md) for full
|
||||
examples covering output formats, context simulation, remote includes, cache,
|
||||
graph modes, and project configuration.
|
||||
|
||||
## Integrations
|
||||
|
||||
### Pre-commit hook
|
||||
|
||||
Add to `.pre-commit-config.yaml` in your repository to run glint automatically whenever `.gitlab-ci.yml` changes:
|
||||
|
||||
```yaml
|
||||
repos:
|
||||
- repo: https://git.k3nny.fr/k3nny/glint
|
||||
rev: v0.2.28
|
||||
hooks:
|
||||
- id: glint
|
||||
```
|
||||
|
||||
Requires [pre-commit](https://pre-commit.com) and Go 1.21+. On first run, pre-commit builds glint from source automatically.
|
||||
|
||||
### GitLab CI component
|
||||
|
||||
Copy [`templates/check.yml`](templates/check.yml) into your repository and include it as a local file, or publish this repository to a GitLab CI/CD Catalog and reference it as a component:
|
||||
|
||||
```yaml
|
||||
# As a local include (copy templates/check.yml to your repo first):
|
||||
include:
|
||||
- local: .gitlab/glint-check.yml
|
||||
|
||||
# As a Catalog component (after publishing to a GitLab instance):
|
||||
include:
|
||||
- component: $CI_SERVER_FQDN/k3nny/glint/check@v0.2.28
|
||||
inputs:
|
||||
stage: validate # optional, default: validate
|
||||
allow_failure: true # optional, default: false
|
||||
```
|
||||
|
||||
The component downloads the glint Linux binary, runs `glint check`, and respects all inputs defined in the `spec:` block.
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
Copy [`action.yml`](action.yml) from this repository, or mirror this repo to GitHub as `k3nny/glint` and reference it directly:
|
||||
|
||||
```yaml
|
||||
- uses: k3nny/glint@v0.2.28
|
||||
with:
|
||||
file: .gitlab-ci.yml # optional, default: .gitlab-ci.yml
|
||||
args: '--format sarif' # optional
|
||||
```
|
||||
|
||||
The action downloads the glint Linux binary into `$RUNNER_TEMP` and runs `glint check`. Only Linux runners are supported (matches the available release binary).
|
||||
|
||||
## Development
|
||||
|
||||
This project uses [Task](https://taskfile.dev) as a task runner.
|
||||
|
||||
+3
-3
@@ -98,9 +98,9 @@ The SVG renderer and terminal tree cover the basic layout. These would bring it
|
||||
|
||||
## CI / editor integration
|
||||
|
||||
- **GitLab CI template** — a `.gitlab-ci.yml` snippet that runs `glint` as a pipeline-validation job before the real pipeline executes; publishable to the GitLab CI/CD Catalog
|
||||
- **GitHub Actions action** — `uses: k3nny/glint@v1` wrapper for repositories that mirror or manage GitLab pipelines from GitHub
|
||||
- **Pre-commit hook** — entry for [pre-commit](https://pre-commit.com) so `glint` runs automatically on `git commit` when `.gitlab-ci.yml` changes
|
||||
- ~~**GitLab CI template**~~ — ✓ shipped v0.2.28; `templates/check.yml` is a GitLab CI/CD Catalog component with `spec:` inputs for stage, file, version, allow_failure, and extra args; also usable as a plain local/remote include
|
||||
- ~~**GitHub Actions action**~~ — ✓ shipped v0.2.28; `action.yml` composite action downloads the glint Linux binary and runs `glint check`; mirror to GitHub as `k3nny/glint` to reference as `uses: k3nny/glint@v0.2.28`
|
||||
- ~~**Pre-commit hook**~~ — ✓ shipped v0.2.28; `.pre-commit-hooks.yaml` defines `language: golang` hook; pre-commit builds glint from source on first run and re-runs on staged `.gitlab-ci.yml` changes
|
||||
- **LSP server** — `glint lsp` mode exposing diagnostics over the Language Server Protocol; enables inline squiggles in VS Code, JetBrains, Neovim, etc. without a dedicated extension
|
||||
- **VS Code extension** — thin wrapper around the LSP server with syntax highlighting for `.gitlab-ci.yml`
|
||||
|
||||
|
||||
+4
-1
@@ -176,10 +176,13 @@ tasks:
|
||||
- "{{.BINARY}}-{{.TAG}}-linux-amd64"
|
||||
|
||||
fuzz:
|
||||
desc: "Run fuzz tests for the YAML parser and sanitizer (set FUZZ_TIME=60s to control duration, default 30s)"
|
||||
desc: "Run all fuzz targets (set FUZZ_TIME=60s to control per-target duration, default 30s)"
|
||||
cmds:
|
||||
- "{{.GO}} test -fuzz=FuzzParseBytes -fuzztime=${FUZZ_TIME:-30s} ./internal/model/"
|
||||
- "{{.GO}} test -fuzz=FuzzSanitizeYAMLEscapes -fuzztime=${FUZZ_TIME:-30s} ./internal/model/"
|
||||
- "{{.GO}} test -fuzz=FuzzEvalIf -fuzztime=${FUZZ_TIME:-30s} ./internal/cicontext/"
|
||||
- "{{.GO}} test -fuzz=FuzzExpandVarRefs -fuzztime=${FUZZ_TIME:-30s} ./internal/cicontext/"
|
||||
- "{{.GO}} test -fuzz=FuzzLint -fuzztime=${FUZZ_TIME:-30s} ./internal/linter/"
|
||||
|
||||
changelog:
|
||||
desc: "Regenerate CHANGELOG.md from git history (requires git-cliff — see README)"
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
# GitHub Actions composite action — glint pipeline validator
|
||||
#
|
||||
# To use this action, mirror this repository to GitHub as k3nny/glint, then:
|
||||
#
|
||||
# - uses: k3nny/glint@v0.2.28
|
||||
# with:
|
||||
# file: .gitlab-ci.yml # optional
|
||||
#
|
||||
# Alternatively, copy this file into your own repository and reference it
|
||||
# as a local action:
|
||||
#
|
||||
# - uses: ./.github/actions/glint
|
||||
|
||||
name: 'glint'
|
||||
description: 'Validate a GitLab CI pipeline file with glint'
|
||||
author: 'k3nny'
|
||||
|
||||
branding:
|
||||
icon: 'check-circle'
|
||||
color: 'orange'
|
||||
|
||||
inputs:
|
||||
version:
|
||||
description: >-
|
||||
glint release tag to install (e.g. 'v0.2.28'). Defaults to 'latest'
|
||||
which resolves to the newest published release.
|
||||
required: false
|
||||
default: 'latest'
|
||||
file:
|
||||
description: 'Path to the pipeline file to validate.'
|
||||
required: false
|
||||
default: '.gitlab-ci.yml'
|
||||
args:
|
||||
description: 'Additional arguments passed to glint check (e.g. --format sarif).'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Install glint
|
||||
shell: bash
|
||||
env:
|
||||
GLINT_VERSION: ${{ inputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ "$GLINT_VERSION" = "latest" ]; then
|
||||
GLINT_VERSION=$(curl -sf \
|
||||
"https://git.k3nny.fr/api/v1/repos/k3nny/glint/releases?limit=1" \
|
||||
| grep '"tag_name"' | head -1 | cut -d'"' -f4)
|
||||
fi
|
||||
DEST="$RUNNER_TEMP/glint-bin"
|
||||
mkdir -p "$DEST"
|
||||
URL="https://git.k3nny.fr/k3nny/glint/releases/download/${GLINT_VERSION}/glint-${GLINT_VERSION}-linux-amd64"
|
||||
curl -sfL "$URL" -o "$DEST/glint"
|
||||
chmod +x "$DEST/glint"
|
||||
echo "$DEST" >> "$GITHUB_PATH"
|
||||
"$DEST/glint" --version
|
||||
|
||||
- name: Run glint check
|
||||
shell: bash
|
||||
run: glint check ${{ inputs.args }} "${{ inputs.file }}"
|
||||
@@ -0,0 +1,85 @@
|
||||
package cicontext
|
||||
|
||||
import "testing"
|
||||
|
||||
// FuzzEvalIf ensures the rules:if: expression evaluator never panics on
|
||||
// arbitrary input. It accepts two strings: the expression and a variable value
|
||||
// substituted for every variable reference encountered.
|
||||
// Run with: go test -fuzz=FuzzEvalIf ./internal/cicontext/
|
||||
func FuzzEvalIf(f *testing.F) {
|
||||
// Seed corpus: representative expressions exercising every code path in
|
||||
// the hand-rolled recursive-descent parser.
|
||||
seeds := []struct{ expr, varVal string }{
|
||||
// Simple comparisons
|
||||
{`$VAR == "main"`, "main"},
|
||||
{`$VAR != "main"`, "main"},
|
||||
{`$VAR == null`, ""},
|
||||
{`$VAR != null`, "x"},
|
||||
// Regex operators
|
||||
{`$VAR =~ /^v\d+\.\d+/`, "v1.2.3"},
|
||||
{`$VAR !~ /^v\d+\.\d+/`, "not-a-version"},
|
||||
{`$VAR =~ /^us\//`, "us/west"},
|
||||
// Boolean operators
|
||||
{`$A == "x" && $B == "y"`, "x"},
|
||||
{`$A == "x" || $B == "y"`, "z"},
|
||||
{`!($VAR == "main")`, "main"},
|
||||
// Nested parens
|
||||
{`($VAR == "a" || $VAR == "b") && $VAR != "c"`, "a"},
|
||||
// Bare true / false
|
||||
{`$VAR == true`, "true"},
|
||||
{`$VAR == false`, "false"},
|
||||
// Integer comparison (GitLab CI compares as strings)
|
||||
{`$VAR == 42`, "42"},
|
||||
// Regex with flags
|
||||
{`$VAR =~ /main/i`, "MAIN"},
|
||||
// Syntax errors / incomplete expressions
|
||||
{``, ""},
|
||||
{`&&`, ""},
|
||||
{`$VAR =~`, "x"},
|
||||
{`($VAR`, "x"},
|
||||
{`$VAR == `, "x"},
|
||||
// Variable syntax variants
|
||||
{`${VAR} == "main"`, "main"},
|
||||
// Deeply nested
|
||||
{`((($VAR == "a")))`, "a"},
|
||||
// String with escapes
|
||||
{`$VAR == "hello\nworld"`, "hello\nworld"},
|
||||
// Null literal
|
||||
{`null == null`, ""},
|
||||
{`$VAR == null`, ""},
|
||||
}
|
||||
for _, s := range seeds {
|
||||
f.Add(s.expr, s.varVal)
|
||||
}
|
||||
|
||||
f.Fuzz(func(t *testing.T, expr, varVal string) {
|
||||
// EvalIf must never panic; it may return any bool.
|
||||
_ = EvalIf(expr, func(string) string { return varVal })
|
||||
_ = EvalIfStrict(expr, func(string) string { return varVal })
|
||||
})
|
||||
}
|
||||
|
||||
// FuzzExpandVarRefs ensures variable expansion in expression strings never
|
||||
// panics and never produces a longer output than the worst-case expansion bound.
|
||||
func FuzzExpandVarRefs(f *testing.F) {
|
||||
seeds := []struct{ s, val string }{
|
||||
{"$VAR", "hello"},
|
||||
{"${VAR}", "hello"},
|
||||
{"$A $B $C", "x"},
|
||||
{"no vars here", ""},
|
||||
{"$$double", "x"},
|
||||
{"$", "x"},
|
||||
{"${", "x"},
|
||||
{"${}", "x"},
|
||||
{"prefix_$VAR_suffix", "mid"},
|
||||
{"$1INVALID", "x"},
|
||||
}
|
||||
for _, s := range seeds {
|
||||
f.Add(s.s, s.val)
|
||||
}
|
||||
|
||||
f.Fuzz(func(t *testing.T, s, val string) {
|
||||
vars := map[string]string{"VAR": val, "A": val, "B": val, "C": val}
|
||||
_ = expandVarRefs(s, vars)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package linter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.k3nny.fr/glint/internal/model"
|
||||
)
|
||||
|
||||
// FuzzLint ensures that the full Parse → Lint pipeline never panics on
|
||||
// arbitrary YAML input. Lint rules type-assert model fields extensively;
|
||||
// this fuzzer drives those assertions against malformed-but-parseable YAML.
|
||||
// Run with: go test -fuzz=FuzzLint ./internal/linter/
|
||||
func FuzzLint(f *testing.F) {
|
||||
seeds := []string{
|
||||
// Minimal valid pipeline
|
||||
"stages: [build]\njob:\n stage: build\n script: echo ok\n",
|
||||
// Manual / delayed / trigger / on_failure job types
|
||||
"job:\n script: ok\n when: manual\n",
|
||||
"job:\n script: ok\n when: delayed\n start_in: 5 minutes\n",
|
||||
"job:\n trigger:\n project: group/repo\n",
|
||||
"job:\n script: ok\n when: on_failure\n",
|
||||
// needs: and dependencies:
|
||||
"stages: [a,b]\na:\n stage: a\n script: ok\nb:\n stage: b\n needs: [a]\n script: ok\n",
|
||||
"stages: [a,b]\na:\n stage: a\n script: ok\nb:\n stage: b\n dependencies: [a]\n script: ok\n",
|
||||
// rules:
|
||||
"job:\n script: ok\n rules:\n - if: '$CI_COMMIT_BRANCH == \"main\"'\n when: on_success\n",
|
||||
// parallel matrix
|
||||
"job:\n script: ok\n parallel:\n matrix:\n - ARCH: [amd64, arm64]\n",
|
||||
// image as string / map
|
||||
"job:\n script: ok\n image: golang:1.21\n",
|
||||
"job:\n script: ok\n image:\n name: golang:1.21\n entrypoint: ['']\n",
|
||||
// artifacts / cache with both string and map when:
|
||||
"job:\n script: ok\n artifacts:\n when: on_success\n paths: [dist/]\n",
|
||||
"job:\n script: ok\n cache:\n key: $CI_COMMIT_REF_SLUG\n paths: [vendor/]\n",
|
||||
// environment / release / coverage
|
||||
"job:\n script: ok\n environment:\n name: production\n url: https://example.com\n",
|
||||
"job:\n script: ok\n release:\n tag_name: $CI_COMMIT_TAG\n description: Release\n",
|
||||
"job:\n script: ok\n coverage: '/^TOTAL.*?(\\d+%)$/'\n",
|
||||
// retry / timeout
|
||||
"job:\n script: ok\n retry: 2\n",
|
||||
"job:\n script: ok\n timeout: 2h30m\n",
|
||||
// workflow
|
||||
"workflow:\n rules:\n - if: '$CI_COMMIT_BRANCH'\n when: always\njob:\n script: ok\n",
|
||||
// extends
|
||||
".base:\n script: ok\nchild:\n extends: .base\n stage: test\n",
|
||||
// id_tokens / secrets
|
||||
"job:\n script: ok\n id_tokens:\n TOKEN:\n aud: https://example.com\n",
|
||||
// services
|
||||
"job:\n script: ok\n services:\n - name: postgres:14\n alias: db\n",
|
||||
// pages job
|
||||
"pages:\n script: make docs\n artifacts:\n paths: [public/]\n",
|
||||
// inherit
|
||||
"default:\n retry: 1\njob:\n script: ok\n inherit:\n default: false\n",
|
||||
// allow_failure
|
||||
"job:\n script: ok\n allow_failure:\n exit_codes: [1, 2]\n",
|
||||
}
|
||||
for _, s := range seeds {
|
||||
f.Add([]byte(s))
|
||||
}
|
||||
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
p, err := model.ParseBytes(data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Lint must never panic regardless of pipeline content.
|
||||
_ = Lint(p, nil)
|
||||
})
|
||||
}
|
||||
@@ -26,6 +26,7 @@ func FuzzParseBytes(f *testing.F) {
|
||||
[]byte("job:\n stage: test\n image:\n name: golang:1.21\n entrypoint: ['']\n parallel:\n matrix:\n - PLATFORM: [linux, darwin]\n script: go build\n"),
|
||||
[]byte("default:\n retry: 2\n timeout: 1h30m\nvariables:\n ENV: production\nstages: [build, test, deploy]\n"),
|
||||
[]byte("&anchor\n script: [echo ok]\njob:\n <<: *anchor\n stage: build\n"),
|
||||
[]byte("?"), // null/empty YAML key — must error, not produce an empty-named job
|
||||
}
|
||||
for _, s := range seeds {
|
||||
f.Add(s)
|
||||
|
||||
@@ -57,6 +57,9 @@ func ParseBytes(data []byte) (*Pipeline, error) {
|
||||
keyNode := root.Content[i]
|
||||
valNode := root.Content[i+1]
|
||||
key := keyNode.Value
|
||||
if key == "" {
|
||||
return nil, fmt.Errorf("job name cannot be empty (null or missing YAML key)")
|
||||
}
|
||||
if ReservedKeys[key] {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -88,6 +88,12 @@ func TestParseBytes_EdgeCases(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Error("wrong field type: expected error from ParseBytes (stage must be string)")
|
||||
}
|
||||
|
||||
// Null/empty YAML key (e.g. bare "?"): job name cannot be empty.
|
||||
_, err = ParseBytes([]byte("?"))
|
||||
if err == nil {
|
||||
t.Error("null key: expected error from ParseBytes (job name cannot be empty)")
|
||||
}
|
||||
}
|
||||
|
||||
// TestParse_ParseBytesError exercises the Parse → ParseBytes error path (line 18).
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
go test fuzz v1
|
||||
[]byte("?")
|
||||
@@ -0,0 +1,62 @@
|
||||
# glint — GitLab CI/CD Catalog component
|
||||
#
|
||||
# Validates a pipeline file with glint before the rest of the pipeline runs.
|
||||
#
|
||||
# Usage (after publishing to a GitLab instance as a Catalog component):
|
||||
#
|
||||
# include:
|
||||
# - component: $CI_SERVER_FQDN/k3nny/glint/check@v0.2.28
|
||||
# inputs:
|
||||
# stage: validate # optional — see inputs below
|
||||
#
|
||||
# Or as a plain remote include (no Catalog required):
|
||||
#
|
||||
# include:
|
||||
# - remote: https://raw.githubusercontent.com/.../templates/check.yml
|
||||
#
|
||||
# Or copy this file into your repository and use a local include.
|
||||
|
||||
spec:
|
||||
inputs:
|
||||
stage:
|
||||
description: "Stage in which to run the glint validation job."
|
||||
default: validate
|
||||
pipeline_file:
|
||||
description: "Path to the pipeline file to validate."
|
||||
default: .gitlab-ci.yml
|
||||
version:
|
||||
description: >-
|
||||
glint release tag to download (e.g. 'v0.2.28'). Use 'latest' to
|
||||
always pull the newest release — not recommended for production
|
||||
pipelines since it may break on a new release.
|
||||
default: latest
|
||||
allow_failure:
|
||||
description: "Set to true to let the job fail without blocking the pipeline."
|
||||
default: false
|
||||
extra_args:
|
||||
description: "Additional arguments passed to 'glint check' (e.g. '--format sarif')."
|
||||
default: ""
|
||||
|
||||
---
|
||||
glint:check:
|
||||
stage: $[[ inputs.stage ]]
|
||||
image: alpine:3.19
|
||||
variables:
|
||||
GLINT_VERSION: "$[[ inputs.version ]]"
|
||||
GLINT_FILE: "$[[ inputs.pipeline_file ]]"
|
||||
GLINT_ARGS: "$[[ inputs.extra_args ]]"
|
||||
before_script:
|
||||
- apk add --no-cache curl
|
||||
- |
|
||||
if [ "$GLINT_VERSION" = "latest" ]; then
|
||||
GLINT_VERSION=$(curl -sf \
|
||||
"https://git.k3nny.fr/api/v1/repos/k3nny/glint/releases?limit=1" \
|
||||
| grep '"tag_name"' | head -1 | cut -d'"' -f4)
|
||||
fi
|
||||
URL="https://git.k3nny.fr/k3nny/glint/releases/download/${GLINT_VERSION}/glint-${GLINT_VERSION}-linux-amd64"
|
||||
curl -sfL "$URL" -o /usr/local/bin/glint
|
||||
chmod +x /usr/local/bin/glint
|
||||
glint --version
|
||||
script:
|
||||
- glint check $GLINT_ARGS "$GLINT_FILE"
|
||||
allow_failure: $[[ inputs.allow_failure ]]
|
||||
Reference in New Issue
Block a user