Skip to content

chore(deps): bump github.com/qmuntal/gltf from 0.28.0 to 0.29.0 in the minor group #83

chore(deps): bump github.com/qmuntal/gltf from 0.28.0 to 0.29.0 in the minor group

chore(deps): bump github.com/qmuntal/gltf from 0.28.0 to 0.29.0 in the minor group #83

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
# Manual trigger. Release is gated on a SUCCESSFUL CI run on main
# (release.yml keys off workflow_run), so a push event GitHub drops during
# an Actions incident leaves main permanently unreleased. Re-running an
# OLDER run is not a substitute: workflow_run hands release.yml that run's
# head SHA, so it would publish from a stale tree. This lets a maintainer
# run CI against main's current tip and let the release chain proceed.
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Least privilege for the whole workflow. The repository default is read/WRITE,
# which every job here would otherwise inherit for no reason — CI only reads the
# tree. A job that genuinely needs more asks for it explicitly (see release.yml,
# which scopes contents: write to the one job that publishes).
permissions:
contents: read
defaults:
run:
shell: bash
jobs:
# A CHANGELOG or docs-only PR cannot break the Go build, but it used to spend
# four runners proving it. This job decides once, and the Go jobs below gate
# on it.
#
# Why a job and not `paths-ignore:` on the workflow itself: Lint, Test,
# Vulnerability Scan and Conventional Commits Check are REQUIRED checks on
# main (ruleset 20694555). A workflow that never starts never reports them,
# and the PR sits un-mergeable forever. A job skipped by `if:` DOES report —
# GitHub counts a skipped required check as passing — so the filter has to
# live inside a workflow that always runs.
#
# CodeQL is deliberately left alone: its required "CodeQL" context comes from
# the github-advanced-security app when results are uploaded, not from a job
# name, so nothing we can skip would still report it.
changes:
name: Detect Changes
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
# Reading the PR's file list goes through the pulls API, which the
# workflow-wide contents: read alone does not cover on a fork PR.
contents: read
pull-requests: read
outputs:
code: ${{ steps.filter.outputs.code }}
steps:
- name: Classify the changed files
id: filter
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
EVENT: ${{ github.event_name }}
PR: ${{ github.event.number }}
BEFORE: ${{ github.event.before }}
AFTER: ${{ github.sha }}
run: |
set -euo pipefail
if [ "$EVENT" = "pull_request" ]; then
files=$(gh api "repos/$REPO/pulls/$PR/files" --paginate --jq '.[].filename')
elif [ -n "${BEFORE:-}" ] && [ "$BEFORE" != "0000000000000000000000000000000000000000" ]; then
files=$(gh api "repos/$REPO/compare/$BEFORE...$AFTER" --jq '.files[].filename')
else
files=''
fi
# An empty list means we could not tell what changed (force push, new
# branch, truncated compare). Run everything — the filter is an
# optimisation and must never be the reason a break slips through.
if [ -z "$files" ] || grep -qvE '(\.md$|^docs/|^mkdocs\.yml$|^requirements-docs\.txt$)' <<< "$files"; then
echo "code=true" >> "$GITHUB_OUTPUT"
echo "Code changed — running the full suite."
else
echo "code=false" >> "$GITHUB_OUTPUT"
echo "Docs-only change — skipping the Go jobs."
fi
echo "$files" | sed 's/^/ /'
conventional-commits:
name: Conventional Commits Check
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Conventional Commits
uses: webiny/action-conventional-commits@7f91b1595ca1951cdb671ddc9f07a49081ec5b69 # v1.4.2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
allowed-commit-types: "feat,fix,cicd,chore,patch,release,test,docs,refactor,ci,dev"
lint:
name: Lint
runs-on: ubuntu-latest
needs: [conventional-commits, changes]
if: needs.changes.outputs.code == 'true'
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1
persist-credentials: false
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: true
- name: golangci-lint
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0
with:
version: v2.12.2
args: --timeout=5m
skip-cache: true
skip-save-cache: true
env:
GOPROXY: https://proxy.golang.org,direct
test:
name: Test
runs-on: ubuntu-latest
needs: [lint, changes]
if: needs.changes.outputs.code == 'true'
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1
persist-credentials: false
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: true
- name: Run tests
# goifc is pure Go with no cgo dependencies. Pinning CGO_ENABLED=0
# asserts that property in CI: if a dependency ever sneaks in a cgo
# requirement, the build fails loudly here instead of silently
# linking against system libraries.
#
# -coverpkg=./... attributes coverage to the package that OWNS the line
# rather than the package whose test executed it, which is the only way
# the cross-package paths (step parsed by a model test, geometry driven
# from Assemble) count at all. It reports one module-wide number instead
# of four per-package ones — 85.3% at the time of writing.
env:
CGO_ENABLED: '0'
run: go test -v -covermode=atomic -coverpkg=./... -coverprofile=coverage.out ./...
# Coverage reporting must never be able to fail a REQUIRED check on
# somebody else's outage, so fail_ci_if_error stays false. The token is
# optional here: blox-eng/goifc is public, so tokenless upload from
# Actions works, and the secret is read for the day that stops being true.
- name: Upload coverage to Codecov
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
files: coverage.out
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
govulncheck:
name: Vulnerability Scan
runs-on: ubuntu-latest
needs: [conventional-commits, changes]
if: needs.changes.outputs.code == 'true'
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1
persist-credentials: false
# govulncheck is the complement to Dependabot, not a duplicate: Dependabot
# tells you a newer version exists, govulncheck tells you whether a known
# vulnerability is actually REACHABLE from this code — and it covers the
# Go standard library, which a dependency bump never touches. The pinned
# toolchain is exactly the kind of thing this catches — and did, on the first
# run: GO-2026-4601 (net/url IPv6 parsing) was reachable from WriteGLB via
# gltf.Encoder.Encode on the then-pinned 1.25.4, fixed in 1.25.8.
- uses: golang/govulncheck-action@032d45514ae346b1db93c04b0c90b841c370344f # v1.1.0
with:
# go-version-input defaults to 'stable', and the action forwards BOTH
# it and go-version-file to setup-go, which then ignores the file and
# warns. That silently scanned whatever 'stable' happened to be rather
# than the toolchain we ship — the exact opposite of the paragraph
# above. Blanking it makes go.mod authoritative for real.
go-version-input: ''
go-version-file: go.mod
go-package: ./...
fuzz:
name: Fuzz Smoke
runs-on: ubuntu-latest
needs: [conventional-commits, changes]
if: needs.changes.outputs.code == 'true'
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1
persist-credentials: false
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: true
# What this job does and does NOT buy, stated honestly: replaying the
# seed corpus and any committed testdata/fuzz/ crashers already happens
# under plain `go test ./...` in the Test job above, which is a REQUIRED
# check. So regression-catching is banked there, not here. All this job
# adds is 60s of coverage-guided exploration per target — thin against a
# strict STEP grammar, but cheap, and it is where a new crasher would
# first show up. Real assurance needs a long scheduled run, not this.
# That run now exists: .github/workflows/fuzz-nightly.yml (30m/target,
# nightly).
# Deliberately not a required check: a fuzz OOM or timeout is infra
# noise and must not block a merge. fuzz-smoke.sh enforces that split —
# it forgives the known -fuzztime shutdown race and nothing else, so a
# crasher still fails the job loudly.
- name: Fuzz the STEP parser
env:
CGO_ENABLED: '0'
run: .github/scripts/fuzz-smoke.sh ./step/ FuzzParseBytes 60s
- name: Fuzz the full assemble path
env:
CGO_ENABLED: '0'
run: .github/scripts/fuzz-smoke.sh . FuzzAssemble 60s
- name: Upload crashers
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: fuzz-crashers
path: '**/testdata/fuzz/**'
if-no-files-found: ignore