mirror of
https://github.com/anchore/syft.git
synced 2026-10-12 14:17:20 +02:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5fba2d0e4 | ||
|
|
4fd1828ba9 |
+23
-10
@@ -2,7 +2,7 @@ tools:
|
||||
# we want to use a pinned version of binny to manage the toolchain (so binny manages itself!)
|
||||
- name: binny
|
||||
version:
|
||||
want: v0.9.0
|
||||
want: v0.8.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: anchore/binny
|
||||
@@ -18,7 +18,7 @@ tools:
|
||||
# used to sign mac binaries at release
|
||||
- name: quill
|
||||
version:
|
||||
want: v0.5.1
|
||||
want: v0.4.2
|
||||
method: github-release
|
||||
with:
|
||||
repo: anchore/quill
|
||||
@@ -26,7 +26,7 @@ tools:
|
||||
# used for linting
|
||||
- name: golangci-lint
|
||||
version:
|
||||
want: v2.4.0
|
||||
want: v1.61.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: golangci/golangci-lint
|
||||
@@ -34,7 +34,7 @@ tools:
|
||||
# used for showing the changelog at release
|
||||
- name: glow
|
||||
version:
|
||||
want: v2.1.1
|
||||
want: v2.0.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: charmbracelet/glow
|
||||
@@ -42,7 +42,7 @@ tools:
|
||||
# used for signing the checksums file at release
|
||||
- name: cosign
|
||||
version:
|
||||
want: v2.5.3
|
||||
want: v2.4.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: sigstore/cosign
|
||||
@@ -58,7 +58,7 @@ tools:
|
||||
# used to release all artifacts
|
||||
- name: goreleaser
|
||||
version:
|
||||
want: v2.11.2
|
||||
want: v2.3.2
|
||||
method: github-release
|
||||
with:
|
||||
repo: goreleaser/goreleaser
|
||||
@@ -87,10 +87,23 @@ tools:
|
||||
with:
|
||||
repo: wagoodman/go-bouncer
|
||||
|
||||
# used for showing benchmark testing
|
||||
- name: benchstat
|
||||
version:
|
||||
want: latest
|
||||
method: go-proxy
|
||||
with:
|
||||
module: golang.org/x/perf
|
||||
allow-unresolved-version: true
|
||||
method: go-install
|
||||
with:
|
||||
entrypoint: cmd/benchstat
|
||||
module: golang.org/x/perf
|
||||
|
||||
# used for running all local and CI tasks
|
||||
- name: task
|
||||
version:
|
||||
want: v3.44.1
|
||||
want: v3.39.2
|
||||
method: github-release
|
||||
with:
|
||||
repo: go-task/task
|
||||
@@ -98,7 +111,7 @@ tools:
|
||||
# used for triggering a release
|
||||
- name: gh
|
||||
version:
|
||||
want: v2.78.0
|
||||
want: v2.57.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: cli/cli
|
||||
@@ -106,7 +119,7 @@ tools:
|
||||
# used to upload test fixture cache
|
||||
- name: oras
|
||||
version:
|
||||
want: v1.2.3
|
||||
want: v1.2.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: oras-project/oras
|
||||
@@ -114,7 +127,7 @@ tools:
|
||||
# used to upload test fixture cache
|
||||
- name: yq
|
||||
version:
|
||||
want: v4.47.1
|
||||
want: v4.44.3
|
||||
method: github-release
|
||||
with:
|
||||
repo: mikefarah/yq
|
||||
|
||||
@@ -5,7 +5,7 @@ inputs:
|
||||
go-version:
|
||||
description: "Go version to install"
|
||||
required: true
|
||||
default: ">= 1.24"
|
||||
default: "1.22.x"
|
||||
go-dependencies:
|
||||
description: "Download go dependencies"
|
||||
required: true
|
||||
@@ -18,9 +18,6 @@ inputs:
|
||||
description: "Download test fixture cache from OCI and github actions"
|
||||
required: true
|
||||
default: "false"
|
||||
tools:
|
||||
description: "whether to install tools"
|
||||
default: "true"
|
||||
bootstrap-apt-packages:
|
||||
description: "Space delimited list of tools to install via apt"
|
||||
default: "libxml2-utils"
|
||||
@@ -29,22 +26,20 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
# note: go mod and build is automatically cached on default with v4+
|
||||
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||
- uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
|
||||
if: inputs.go-version != ''
|
||||
with:
|
||||
go-version: ${{ inputs.go-version }}
|
||||
|
||||
- name: Restore tool cache
|
||||
if: inputs.tools == 'true'
|
||||
id: tool-cache
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ${{ github.workspace }}/.tool
|
||||
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('.binny.yaml') }}
|
||||
|
||||
- name: Install project tools
|
||||
shell: bash
|
||||
if: inputs.tools == 'true'
|
||||
run: make tools
|
||||
|
||||
- name: Install go dependencies
|
||||
@@ -55,15 +50,12 @@ runs:
|
||||
- name: Install apt packages
|
||||
if: inputs.bootstrap-apt-packages != ''
|
||||
shell: bash
|
||||
env:
|
||||
APT_PACKAGES: ${{ inputs.bootstrap-apt-packages }}
|
||||
run: |
|
||||
IFS=' ' read -ra packages <<< "$APT_PACKAGES"
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y "${packages[@]}"
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y ${{ inputs.bootstrap-apt-packages }}
|
||||
|
||||
- name: Restore ORAS cache from github actions
|
||||
if: inputs.download-test-fixture-cache == 'true'
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2
|
||||
with:
|
||||
path: ${{ github.workspace }}/.tmp/oras-cache
|
||||
key: ${{ inputs.cache-key-prefix }}-oras-cache
|
||||
|
||||
@@ -19,7 +19,7 @@ updates:
|
||||
- "dependencies"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/.github/actions/bootstrap"
|
||||
directory: "/.github/actions/boostrap"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 10
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# Description
|
||||
|
||||
Please include a summary of the changes along with any relevant motivation and context,
|
||||
or link to an issue where this is explained.
|
||||
|
||||
<!-- If this completes an issue, please include: -->
|
||||
|
||||
- Fixes
|
||||
|
||||
## Type of change
|
||||
|
||||
<!-- Delete any that are not relevant -->
|
||||
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (please discuss with the team first; Syft is 1.0 software and we won't accept breaking changes without going to 2.0)
|
||||
- [ ] Documentation (updates the documentation)
|
||||
- [ ] Chore (improve the developer experience, fix a test flake, etc, without changing the visible behavior of Syft)
|
||||
- [ ] Performance (make Syft run faster or use less memory, without changing visible behavior much)
|
||||
|
||||
# Checklist:
|
||||
|
||||
- [ ] I have added unit tests that cover changed behavior
|
||||
- [ ] I have tested my code in common scenarios and confirmed there are no regressions
|
||||
- [ ] I have added comments to my code, particularly in hard-to-understand sections
|
||||
@@ -86,10 +86,8 @@ def main(file_path: str | None):
|
||||
show("The following paths are missing or have no content, but have corresponding .fingerprint files:")
|
||||
for path in sorted(missing_content):
|
||||
show(f"- {path}")
|
||||
# when adding new cache directories there is a time where it is not possible to have this directory without
|
||||
# running the tests first... but this step is a prerequisite for running the tests. We should not block on this.
|
||||
# show("Please ensure these paths exist and have content if they are directories.")
|
||||
# exit(1)
|
||||
show("Please ensure these paths exist and have content if they are directories.")
|
||||
exit(1)
|
||||
|
||||
sha256_hash = calculate_sha256(fingerprint_contents)
|
||||
|
||||
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
set -ue
|
||||
|
||||
BIN="syft"
|
||||
VERSION_FILE="VERSION"
|
||||
VERSION=$1
|
||||
|
||||
# the source of truth as to whether we want to notify users of an update is if the release just created is NOT
|
||||
# flagged as a pre-release on github
|
||||
if [[ "$(curl -SsL https://api.github.com/repos/anchore/${BIN}/releases/tags/${VERSION} | jq .prerelease)" == "true" ]] ; then
|
||||
echo "skipping publishing a version file (this is a pre-release: ${VERSION})"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "creating and publishing version file (${VERSION})"
|
||||
|
||||
# create a version file for version-update checks
|
||||
echo "${VERSION}" | tee "${VERSION_FILE}"
|
||||
|
||||
# upload the version file that supports the application version update check
|
||||
export AWS_DEFAULT_REGION=us-west-2
|
||||
aws s3 cp "${VERSION_FILE}" s3://toolbox-data.anchore.io/${BIN}/releases/latest/VERSION
|
||||
@@ -0,0 +1,62 @@
|
||||
name: "Benchmark testing"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
|
||||
Benchmark-Test:
|
||||
name: "Benchmark tests"
|
||||
runs-on: ubuntu-20.04
|
||||
# note: we want benchmarks to run on pull_request events in order to publish results to a sticky comment, and
|
||||
# we also want to run on push such that merges to main are recorded to the cache. For this reason we don't filter
|
||||
# the job by event.
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore base benchmark result
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: test/results/benchmark-main.txt
|
||||
# use base sha for PR or new commit hash for main push in benchmark result key
|
||||
key: ${{ runner.os }}-bench-${{ (github.event.pull_request.base.sha != github.event.after) && github.event.pull_request.base.sha || github.event.after }}
|
||||
|
||||
- name: Run benchmark tests
|
||||
id: benchmark
|
||||
run: |
|
||||
REF_NAME=${GITHUB_REF##*/} make benchmark
|
||||
OUTPUT=$(make show-benchstat)
|
||||
OUTPUT="${OUTPUT//'%'/'%25'}" # URL encode all '%' characters
|
||||
OUTPUT="${OUTPUT//$'\n'/'%0A'}" # URL encode all '\n' characters
|
||||
OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters
|
||||
echo "result=$OUTPUT" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
with:
|
||||
name: benchmark-test-results
|
||||
path: test/results/**/*
|
||||
|
||||
- name: Update PR benchmark results comment
|
||||
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0
|
||||
continue-on-error: true
|
||||
with:
|
||||
header: benchmark
|
||||
message: |
|
||||
### Benchmark Test Results
|
||||
|
||||
<details>
|
||||
<summary>Benchmark results from the latest changes vs base branch</summary>
|
||||
|
||||
```
|
||||
${{ steps.benchmark.outputs.result }}
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-22.04-4core-16gb
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
|
||||
permissions:
|
||||
security-events: write
|
||||
|
||||
@@ -36,18 +36,16 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 #v5.5.0
|
||||
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 #v5.0.2
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 #v3.29.5
|
||||
uses: github/codeql-action/init@294a9d92911152fe08befb9ec03e240add280cb3 #v3.26.8
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -58,7 +56,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@3c3833e0f8c1c83d449a7478aa59c036a9165498 #v3.29.5
|
||||
uses: github/codeql-action/autobuild@294a9d92911152fe08befb9ec03e240add280cb3 #v3.26.8
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -72,4 +70,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 #v3.29.5
|
||||
uses: github/codeql-action/analyze@294a9d92911152fe08befb9ec03e240add280cb3 #v3.26.8
|
||||
|
||||
@@ -28,15 +28,9 @@ jobs:
|
||||
label:
|
||||
name: "Label changes"
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- run: python .github/scripts/labeler.py
|
||||
env:
|
||||
@@ -46,7 +40,7 @@ jobs:
|
||||
|
||||
- name: Delete existing comment
|
||||
if: ${{ hashFiles( env.CI_COMMENT_FILE ) == '' }}
|
||||
uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 #v2.9.4
|
||||
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0
|
||||
with:
|
||||
header: ${{ env.COMMENT_HEADER }}
|
||||
hide: true
|
||||
@@ -54,7 +48,7 @@ jobs:
|
||||
|
||||
- name: Add comment
|
||||
if: ${{ hashFiles( env.CI_COMMENT_FILE ) != '' }}
|
||||
uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 #v2.9.4
|
||||
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0
|
||||
with:
|
||||
header: ${{ env.COMMENT_HEADER }}
|
||||
path: ${{ env.CI_COMMENT_FILE }}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
name: "Release: version file"
|
||||
|
||||
on:
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: release version to update the version file with (prefixed with v)
|
||||
required: true
|
||||
|
||||
workflow_call:
|
||||
inputs:
|
||||
version:
|
||||
type: string
|
||||
description: release version to update the version file with (prefixed with v)
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Update version file
|
||||
run: make ci-release-version-file
|
||||
env:
|
||||
RELEASE_VERSION: ${{ github.event.inputs.version }}
|
||||
# for updating the VERSION file in S3...
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.TOOLBOX_AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.TOOLBOX_AWS_SECRET_ACCESS_KEY }}
|
||||
@@ -13,11 +13,9 @@ on:
|
||||
jobs:
|
||||
quality-gate:
|
||||
environment: release
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Check if running on main
|
||||
if: github.ref != 'refs/heads/main'
|
||||
@@ -30,10 +28,8 @@ jobs:
|
||||
- name: Check if tag already exists
|
||||
# note: this will fail if the tag already exists
|
||||
run: |
|
||||
[[ "$VERSION" == v* ]] || (echo "version '$VERSION' does not have a 'v' prefix" && exit 1)
|
||||
git tag "$VERSION"
|
||||
env:
|
||||
VERSION: ${{ github.event.inputs.version }}
|
||||
[[ "${{ github.event.inputs.version }}" == v* ]] || (echo "version '${{ github.event.inputs.version }}' does not have a 'v' prefix" && exit 1)
|
||||
git tag ${{ github.event.inputs.version }}
|
||||
|
||||
- name: Check static analysis results
|
||||
uses: fountainhead/action-wait-for-check@5a908a24814494009c4bb27c242ea38c93c593be # v1.2.0
|
||||
@@ -91,47 +87,39 @@ jobs:
|
||||
|
||||
- name: Quality gate
|
||||
if: steps.static-analysis.outputs.conclusion != 'success' || steps.unit.outputs.conclusion != 'success' || steps.integration.outputs.conclusion != 'success' || steps.cli-linux.outputs.conclusion != 'success' || steps.acceptance-linux.outputs.conclusion != 'success' || steps.acceptance-mac.outputs.conclusion != 'success'
|
||||
env:
|
||||
STATIC_ANALYSIS_STATUS: ${{ steps.static-analysis.conclusion }}
|
||||
UNIT_TEST_STATUS: ${{ steps.unit.outputs.conclusion }}
|
||||
INTEGRATION_TEST_STATUS: ${{ steps.integration.outputs.conclusion }}
|
||||
ACCEPTANCE_LINUX_STATUS: ${{ steps.acceptance-linux.outputs.conclusion }}
|
||||
ACCEPTANCE_MAC_STATUS: ${{ steps.acceptance-mac.outputs.conclusion }}
|
||||
CLI_LINUX_STATUS: ${{ steps.cli-linux.outputs.conclusion }}
|
||||
run: |
|
||||
echo "Static Analysis Status: $STATIC_ANALYSIS_STATUS"
|
||||
echo "Unit Test Status: $UNIT_TEST_STATUS"
|
||||
echo "Integration Test Status: $INTEGRATION_TEST_STATUS"
|
||||
echo "Acceptance Test (Linux) Status: $ACCEPTANCE_LINUX_STATUS"
|
||||
echo "Acceptance Test (Mac) Status: $ACCEPTANCE_MAC_STATUS"
|
||||
echo "CLI Test (Linux) Status: $CLI_LINUX_STATUS"
|
||||
echo "Static Analysis Status: ${{ steps.static-analysis.conclusion }}"
|
||||
echo "Unit Test Status: ${{ steps.unit.outputs.conclusion }}"
|
||||
echo "Integration Test Status: ${{ steps.integration.outputs.conclusion }}"
|
||||
echo "Acceptance Test (Linux) Status: ${{ steps.acceptance-linux.outputs.conclusion }}"
|
||||
echo "Acceptance Test (Mac) Status: ${{ steps.acceptance-mac.outputs.conclusion }}"
|
||||
echo "CLI Test (Linux) Status: ${{ steps.cli-linux.outputs.conclusion }}"
|
||||
false
|
||||
|
||||
release:
|
||||
needs: [quality-gate]
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
# required for goreleaser signs section with cosign
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: true
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 #v3.5.0
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 #v3.3.0
|
||||
with:
|
||||
username: ${{ secrets.ANCHOREOSSWRITE_DH_USERNAME }}
|
||||
password: ${{ secrets.ANCHOREOSSWRITE_DH_PAT }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 #v3.5.0
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 #v3.3.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
@@ -141,11 +129,10 @@ jobs:
|
||||
run: |
|
||||
git config --global user.name "anchoreci"
|
||||
git config --global user.email "anchoreci@users.noreply.github.com"
|
||||
git tag -a "$VERSION" -m "Release $VERSION"
|
||||
git tag -a ${{ github.event.inputs.version }} -m "Release ${{ github.event.inputs.version }}"
|
||||
git push origin --tags
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
VERSION: ${{ github.event.inputs.version }}
|
||||
|
||||
- name: Build & publish release artifacts
|
||||
run: make ci-release
|
||||
@@ -161,13 +148,12 @@ jobs:
|
||||
# for updating brew formula in anchore/homebrew-syft
|
||||
GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }}
|
||||
|
||||
- uses: anchore/sbom-action@da167eac915b4e86f08b264dbdbc867b61be6f0c #v0.20.5
|
||||
- uses: anchore/sbom-action@61119d458adab75f756bc0b9e4bde25725f86a7a #v0.17.2
|
||||
continue-on-error: true
|
||||
with:
|
||||
file: go.mod
|
||||
artifact-name: sbom.spdx.json
|
||||
|
||||
- uses: 8398a7/action-slack@1750b5085f3ec60384090fb7c52965ef822e869e #v3.18.0
|
||||
- uses: 8398a7/action-slack@28ba43ae48961b90635b50953d216767a6bea486 #v3.16.2
|
||||
continue-on-error: true
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
@@ -177,17 +163,9 @@ jobs:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TOOLBOX_WEBHOOK_URL }}
|
||||
if: ${{ success() }}
|
||||
|
||||
release-install-script:
|
||||
release-version-file:
|
||||
needs: [release]
|
||||
if: ${{ needs.release.result == 'success' }}
|
||||
uses: "anchore/workflows/.github/workflows/release-install-script.yaml@main"
|
||||
uses: ./.github/workflows/release-version-file.yaml
|
||||
with:
|
||||
tag: ${{ github.event.inputs.version }}
|
||||
secrets:
|
||||
# needed for r2...
|
||||
R2_INSTALL_ACCESS_KEY_ID: ${{ secrets.OSS_R2_INSTALL_ACCESS_KEY_ID }}
|
||||
R2_INSTALL_SECRET_ACCESS_KEY: ${{ secrets.OSS_R2_INSTALL_SECRET_ACCESS_KEY }}
|
||||
R2_ENDPOINT: ${{ secrets.TOOLBOX_CLOUDFLARE_R2_ENDPOINT }}
|
||||
# needed for s3...
|
||||
S3_INSTALL_AWS_ACCESS_KEY_ID: ${{ secrets.TOOLBOX_AWS_ACCESS_KEY_ID }}
|
||||
S3_INSTALL_AWS_SECRET_ACCESS_KEY: ${{ secrets.TOOLBOX_AWS_SECRET_ACCESS_KEY }}
|
||||
version: ${{ github.event.inputs.version }}
|
||||
secrets: inherit
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
name: "Manage Awaiting Response Label"
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
run:
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
uses: "anchore/workflows/.github/workflows/remove-awaiting-response-label.yaml@main"
|
||||
secrets:
|
||||
token: ${{ secrets.OSS_PROJECT_GH_TOKEN }}
|
||||
@@ -15,13 +15,10 @@ jobs:
|
||||
name: "Publish test fixture image cache"
|
||||
# we use this runner to get enough storage space for docker images and fixture cache
|
||||
runs-on: ubuntu-22.04-4core-16gb
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
permissions:
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -36,9 +33,7 @@ jobs:
|
||||
DOWNLOAD_TEST_FIXTURE_CACHE: "false"
|
||||
|
||||
- name: Login to GitHub Container Registry (ORAS)
|
||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | .tool/oras login ghcr.io -u "$ACTOR" --password-stdin
|
||||
env:
|
||||
ACTOR: ${{ github.actor }}
|
||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | .tool/oras login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||
|
||||
- name: Publish test fixture cache
|
||||
run: make upload-test-fixture-cache
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
name: PR to update Anchore dependencies
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
repos:
|
||||
description: "List of dependencies to update"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
update:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'anchore' # only run for main repo (not forks)
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
with:
|
||||
tools: false
|
||||
bootstrap-apt-packages: ""
|
||||
|
||||
- name: Update dependencies
|
||||
id: update
|
||||
uses: anchore/workflows/.github/actions/update-go-dependencies@main
|
||||
with:
|
||||
repos: ${{ github.event.inputs.repos }}
|
||||
|
||||
- uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a #v2.1.0
|
||||
id: generate-token
|
||||
with:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e #v7.0.8
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
draft: ${{ steps.update.outputs.draft }}
|
||||
# do not change this branch, as other workflows depend on it
|
||||
branch: auto/integration
|
||||
labels: dependencies,pre-release
|
||||
commit-message: "chore(deps): update anchore dependencies"
|
||||
title: "chore(deps): update anchore dependencies"
|
||||
body: ${{ steps.update.outputs.summary }}
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
@@ -13,9 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -51,7 +49,7 @@ jobs:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e #v7.0.8
|
||||
- uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f #v7.0.5
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -16,9 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -35,7 +33,7 @@ jobs:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e #v7.0.8
|
||||
- uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f #v7.0.5
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
@@ -47,7 +45,7 @@ jobs:
|
||||
Update CPE dictionary index based on the latest available CPE dictionary
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
- uses: 8398a7/action-slack@1750b5085f3ec60384090fb7c52965ef822e869e #v3.18.0
|
||||
- uses: 8398a7/action-slack@28ba43ae48961b90635b50953d216767a6bea486 #v3.16.2
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
fields: workflow,eventName,job
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
name: PR for latest Stereoscope release
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 8 * * *" # 3 AM EST
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.21.x"
|
||||
GO_STABLE_VERSION: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
upgrade-stereoscope:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'anchore/syft' # only run for main repo
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 #v5.0.2
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
stable: ${{ env.GO_STABLE_VERSION }}
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- run: |
|
||||
LATEST_VERSION=$(git ls-remote https://github.com/anchore/stereoscope main | head -n1 | awk '{print $1;}')
|
||||
|
||||
# update go.mod
|
||||
go get github.com/anchore/stereoscope@$LATEST_VERSION
|
||||
go mod tidy
|
||||
|
||||
# export the version for use with create-pull-request
|
||||
echo "LATEST_VERSION=$LATEST_VERSION" >> $GITHUB_OUTPUT
|
||||
id: latest-version
|
||||
|
||||
- uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a #v2.1.0
|
||||
id: generate-token
|
||||
with:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f #v7.0.5
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
branch: auto/latest-stereoscope
|
||||
labels: dependencies
|
||||
commit-message: "chore(deps): update stereoscope to ${{ steps.latest-version.outputs.LATEST_VERSION }}"
|
||||
title: "chore(deps): update stereoscope to ${{ steps.latest-version.outputs.LATEST_VERSION }}"
|
||||
body: |
|
||||
Update Stereoscope to ${{ steps.latest-version.outputs.LATEST_VERSION }}
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
@@ -1,35 +0,0 @@
|
||||
name: "Validate GitHub Actions"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/**'
|
||||
- '.github/actions/**'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- '.github/workflows/**'
|
||||
- '.github/actions/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
zizmor:
|
||||
name: "Lint"
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write # for uploading SARIF results
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run zizmor"
|
||||
uses: zizmorcore/zizmor-action@5ca5fc7a4779c5263a3ffa0e1f693009994446d1 # v0.1.2
|
||||
with:
|
||||
config-file: .github/zizmor.yml
|
||||
sarif-upload: true
|
||||
inputs: .github
|
||||
@@ -15,11 +15,9 @@ jobs:
|
||||
Static-Analysis:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Static analysis"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -31,12 +29,9 @@ jobs:
|
||||
Unit-Test:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Unit tests"
|
||||
# we need more storage than what's on the default runner
|
||||
runs-on: ubuntu-22.04-4core-16gb
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -50,11 +45,9 @@ jobs:
|
||||
Integration-Test:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Integration tests"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -70,11 +63,9 @@ jobs:
|
||||
|
||||
Build-Snapshot-Artifacts:
|
||||
name: "Build snapshot artifacts"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -84,13 +75,10 @@ jobs:
|
||||
- name: Build snapshot artifacts
|
||||
run: make snapshot
|
||||
|
||||
- name: Smoke test snapshot build
|
||||
run: make snapshot-smoke-test
|
||||
|
||||
# why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach).
|
||||
# see https://github.com/actions/upload-artifact/issues/199 for more info
|
||||
- name: Upload snapshot artifacts
|
||||
uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 #v4.2.4
|
||||
uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
# we need to preserve the snapshot data itself as well as the task data that confirms if the
|
||||
# snapshot build is stale or not. Otherwise the downstream jobs will attempt to rebuild the snapshot
|
||||
@@ -101,72 +89,13 @@ jobs:
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
|
||||
|
||||
Upload-Snapshot-Artifacts:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Upload snapshot artifacts"
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
with:
|
||||
download-test-fixture-cache: true
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 #v4.2.4
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
.task
|
||||
fail-on-cache-miss: true
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
|
||||
# workaround for https://github.com/actions/cache/issues/1265
|
||||
- name: (cache-miss) Snapshot build missing
|
||||
if: steps.snapshot-cache.outputs.cache-hit != 'true'
|
||||
run: echo "unable to download snapshots from previous job" && false
|
||||
|
||||
- run: npm install @actions/artifact@2.2.2
|
||||
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { readdirSync } = require('fs')
|
||||
const { DefaultArtifactClient } = require('@actions/artifact')
|
||||
const artifact = new DefaultArtifactClient()
|
||||
const ls = d => readdirSync(d, { withFileTypes: true })
|
||||
const baseDir = "./snapshot"
|
||||
const dirs = ls(baseDir).filter(f => f.isDirectory()).map(f => f.name)
|
||||
const uploads = []
|
||||
for (const dir of dirs) {
|
||||
// uploadArtifact returns Promise<{id, size}>
|
||||
uploads.push(artifact.uploadArtifact(
|
||||
// name of the archive:
|
||||
`${dir}`,
|
||||
// array of all files to include:
|
||||
ls(`${baseDir}/${dir}`).map(f => `${baseDir}/${dir}/${f.name}`),
|
||||
// base directory to trim from entries:
|
||||
`${baseDir}/${dir}`,
|
||||
{ retentionDays: 30 }
|
||||
))
|
||||
}
|
||||
// wait for all uploads to finish
|
||||
Promise.all(uploads)
|
||||
|
||||
Acceptance-Linux:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Acceptance tests (Linux)"
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -175,7 +104,7 @@ jobs:
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 #v4.2.4
|
||||
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
@@ -210,11 +139,9 @@ jobs:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Install Cosign
|
||||
uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
|
||||
uses: sigstore/cosign-installer@v3.6.0
|
||||
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -225,7 +152,7 @@ jobs:
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 #v4.2.4
|
||||
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
@@ -249,11 +176,9 @@ jobs:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "CLI tests (Linux)"
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
@@ -262,7 +187,7 @@ jobs:
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 #v4.2.4
|
||||
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
@@ -282,18 +207,15 @@ jobs:
|
||||
Cleanup-Cache:
|
||||
name: "Cleanup snapshot cache"
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
actions: write
|
||||
needs:
|
||||
- Acceptance-Linux
|
||||
- Acceptance-Mac
|
||||
- Cli-Linux
|
||||
- Upload-Snapshot-Artifacts
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7
|
||||
|
||||
- name: Delete snapshot cache
|
||||
run: gh cache delete "snapshot-build-${{ github.run_id }}"
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
rules:
|
||||
unpinned-uses:
|
||||
ignore:
|
||||
# Allow unpinned uses of trusted internal anchore/workflows actions
|
||||
- update-anchore-dependencies.yml
|
||||
|
||||
dangerous-triggers:
|
||||
ignore:
|
||||
# Safe use of pull_request_target - only runs trusted scripts from base repo,
|
||||
# never checks out PR code, needs secrets for labeling PRs from forks
|
||||
- detect-schema-changes.yaml
|
||||
+41
-49
@@ -1,8 +1,14 @@
|
||||
version: "2"
|
||||
run:
|
||||
tests: false
|
||||
issues:
|
||||
max-same-issues: 25
|
||||
|
||||
# TODO: enable this when we have coverage on docstring comments
|
||||
# # The list of ids of default excludes to include or disable.
|
||||
# include:
|
||||
# - EXC0002 # disable excluding of issues about comments from golint
|
||||
|
||||
linters:
|
||||
default: none
|
||||
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
||||
disable-all: true
|
||||
enable:
|
||||
- asciicheck
|
||||
- bodyclose
|
||||
@@ -15,8 +21,11 @@ linters:
|
||||
- goconst
|
||||
- gocritic
|
||||
- gocyclo
|
||||
- gofmt
|
||||
- goimports
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
@@ -24,35 +33,38 @@ linters:
|
||||
- nolintlint
|
||||
- revive
|
||||
- staticcheck
|
||||
- stylecheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- whitespace
|
||||
settings:
|
||||
funlen:
|
||||
lines: 70
|
||||
statements: 50
|
||||
gocritic:
|
||||
enabled-checks:
|
||||
- deferInLoop
|
||||
- ruleguard
|
||||
settings:
|
||||
ruleguard:
|
||||
rules: test/rules/rules.go
|
||||
gosec:
|
||||
excludes:
|
||||
- G115
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
||||
linters-settings:
|
||||
funlen:
|
||||
# Checks the number of lines in a function.
|
||||
# If lower than 0, disable the check.
|
||||
# Default: 60
|
||||
lines: 70
|
||||
# Checks the number of statements in a function.
|
||||
# If lower than 0, disable the check.
|
||||
# Default: 40
|
||||
statements: 50
|
||||
gocritic:
|
||||
enabled-checks:
|
||||
- deferInLoop
|
||||
- ruleguard
|
||||
settings:
|
||||
ruleguard:
|
||||
rules: "test/rules/rules.go"
|
||||
gosec:
|
||||
excludes:
|
||||
- G115
|
||||
output:
|
||||
uniq-by-line: false
|
||||
run:
|
||||
timeout: 10m
|
||||
tests: false
|
||||
|
||||
# do not enable...
|
||||
# - deadcode # The owner seems to have abandoned the linter. Replaced by "unused".
|
||||
@@ -79,23 +91,3 @@ linters:
|
||||
# - testpackage
|
||||
# - varcheck # The owner seems to have abandoned the linter. Replaced by "unused".
|
||||
# - wsl # this doens't have an auto-fixer yet and is pretty noisy (https://github.com/bombsimon/wsl/issues/90)
|
||||
|
||||
issues:
|
||||
max-same-issues: 25
|
||||
uniq-by-line: false
|
||||
|
||||
# TODO: enable this when we have coverage on docstring comments
|
||||
# # The list of ids of default excludes to include or disable.
|
||||
# include:
|
||||
# - EXC0002 # disable excluding of issues about comments from golint
|
||||
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
||||
+120
-189
@@ -1,11 +1,11 @@
|
||||
version: 2
|
||||
project_name: syft
|
||||
|
||||
release:
|
||||
prerelease: auto
|
||||
draft: false
|
||||
|
||||
env:
|
||||
# required to support multi architecture docker builds
|
||||
- DOCKER_CLI_EXPERIMENTAL=enabled
|
||||
- CGO_ENABLED=0
|
||||
|
||||
@@ -13,8 +13,14 @@ builds:
|
||||
- id: linux-build
|
||||
dir: ./cmd/syft
|
||||
binary: syft
|
||||
goos: [linux]
|
||||
goarch: [amd64, arm64, ppc64le, s390x]
|
||||
goos:
|
||||
- linux
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
- ppc64le
|
||||
- s390x
|
||||
# set the modified timestamp on the output binary to the git timestamp to ensure a reproducible build
|
||||
mod_timestamp: &build-timestamp '{{ .CommitTimestamp }}'
|
||||
ldflags: &build-ldflags |
|
||||
-w
|
||||
@@ -28,8 +34,11 @@ builds:
|
||||
- id: darwin-build
|
||||
dir: ./cmd/syft
|
||||
binary: syft
|
||||
goos: [darwin]
|
||||
goarch: [amd64, arm64]
|
||||
goos:
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
mod_timestamp: *build-timestamp
|
||||
ldflags: *build-ldflags
|
||||
hooks:
|
||||
@@ -41,43 +50,115 @@ builds:
|
||||
- id: windows-build
|
||||
dir: ./cmd/syft
|
||||
binary: syft
|
||||
goos: [windows]
|
||||
goarch: [amd64]
|
||||
goos:
|
||||
- windows
|
||||
goarch:
|
||||
- amd64
|
||||
mod_timestamp: *build-timestamp
|
||||
ldflags: *build-ldflags
|
||||
|
||||
archives:
|
||||
- id: linux-archives
|
||||
ids: [linux-build]
|
||||
builds:
|
||||
- linux-build
|
||||
|
||||
# note: the signing process is depending on tar.gz archives. If this format changes then .github/scripts/apple-signing/*.sh will need to be adjusted
|
||||
- id: darwin-archives
|
||||
ids: [darwin-build]
|
||||
builds:
|
||||
- darwin-build
|
||||
|
||||
- id: windows-archives
|
||||
formats:
|
||||
- zip
|
||||
ids: [windows-build]
|
||||
format: zip
|
||||
builds:
|
||||
- windows-build
|
||||
|
||||
nfpms:
|
||||
- license: "Apache 2.0"
|
||||
maintainer: "Anchore, Inc"
|
||||
homepage: &website "https://github.com/anchore/syft"
|
||||
description: &description "A tool that generates a Software Bill Of Materials (SBOM) from container images and filesystems"
|
||||
formats: [rpm, deb]
|
||||
formats:
|
||||
- rpm
|
||||
- deb
|
||||
|
||||
brews:
|
||||
- repository:
|
||||
owner: anchore
|
||||
name: homebrew-syft
|
||||
token: "{{.Env.GITHUB_BREW_TOKEN}}"
|
||||
ids: [darwin-archives, linux-archives]
|
||||
ids:
|
||||
- darwin-archives
|
||||
- linux-archives
|
||||
homepage: *website
|
||||
description: *description
|
||||
license: "Apache License 2.0"
|
||||
|
||||
dockers:
|
||||
# production images...
|
||||
- image_templates:
|
||||
- anchore/syft:{{.Tag}}-amd64
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-amd64
|
||||
- anchore/syft:debug
|
||||
- anchore/syft:{{.Tag}}-debug
|
||||
- ghcr.io/anchore/syft:debug
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug
|
||||
goarch: amd64
|
||||
dockerfile: Dockerfile.debug
|
||||
use: buildx
|
||||
build_flag_templates:
|
||||
- "--platform=linux/amd64"
|
||||
- "--build-arg=BUILD_DATE={{.Date}}"
|
||||
- "--build-arg=BUILD_VERSION={{.Version}}"
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
- image_templates:
|
||||
- anchore/syft:debug-arm64v8
|
||||
- anchore/syft:{{.Tag}}-debug-arm64v8
|
||||
- ghcr.io/anchore/syft:debug-arm64v8
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-arm64v8
|
||||
goarch: arm64
|
||||
dockerfile: Dockerfile.debug
|
||||
use: buildx
|
||||
build_flag_templates:
|
||||
- "--platform=linux/arm64/v8"
|
||||
- "--build-arg=BUILD_DATE={{.Date}}"
|
||||
- "--build-arg=BUILD_VERSION={{.Version}}"
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
- image_templates:
|
||||
- anchore/syft:debug-ppc64le
|
||||
- anchore/syft:{{.Tag}}-debug-ppc64le
|
||||
- ghcr.io/anchore/syft:debug-ppc64le
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-ppc64le
|
||||
goarch: ppc64le
|
||||
dockerfile: Dockerfile.debug
|
||||
use: buildx
|
||||
build_flag_templates:
|
||||
- "--platform=linux/ppc64le"
|
||||
- "--build-arg=BUILD_DATE={{.Date}}"
|
||||
- "--build-arg=BUILD_VERSION={{.Version}}"
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
- image_templates:
|
||||
- anchore/syft:debug-s390x
|
||||
- anchore/syft:{{.Tag}}-debug-s390x
|
||||
- ghcr.io/anchore/syft:debug-s390x
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-s390x
|
||||
goarch: s390x
|
||||
dockerfile: Dockerfile.debug
|
||||
use: buildx
|
||||
build_flag_templates:
|
||||
- "--platform=linux/s390x"
|
||||
- "--build-arg=BUILD_DATE={{.Date}}"
|
||||
- "--build-arg=BUILD_VERSION={{.Version}}"
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
- image_templates:
|
||||
- anchore/syft:latest
|
||||
- anchore/syft:{{.Tag}}
|
||||
- ghcr.io/anchore/syft:latest
|
||||
- ghcr.io/anchore/syft:{{.Tag}}
|
||||
goarch: amd64
|
||||
dockerfile: Dockerfile
|
||||
use: buildx
|
||||
@@ -127,201 +208,51 @@ dockers:
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
# nonroot images...
|
||||
- image_templates:
|
||||
- anchore/syft:{{.Tag}}-nonroot-amd64
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-nonroot-amd64
|
||||
goarch: amd64
|
||||
dockerfile: Dockerfile.nonroot
|
||||
use: buildx
|
||||
build_flag_templates:
|
||||
- "--platform=linux/amd64"
|
||||
- "--build-arg=BUILD_DATE={{.Date}}"
|
||||
- "--build-arg=BUILD_VERSION={{.Version}}"
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
- image_templates:
|
||||
- anchore/syft:{{.Tag}}-nonroot-arm64v8
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-nonroot-arm64v8
|
||||
goarch: arm64
|
||||
dockerfile: Dockerfile.nonroot
|
||||
use: buildx
|
||||
build_flag_templates:
|
||||
- "--platform=linux/arm64/v8"
|
||||
- "--build-arg=BUILD_DATE={{.Date}}"
|
||||
- "--build-arg=BUILD_VERSION={{.Version}}"
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
- image_templates:
|
||||
- anchore/syft:{{.Tag}}-nonroot-ppc64le
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-nonroot-ppc64le
|
||||
goarch: ppc64le
|
||||
dockerfile: Dockerfile.nonroot
|
||||
use: buildx
|
||||
build_flag_templates:
|
||||
- "--platform=linux/ppc64le"
|
||||
- "--build-arg=BUILD_DATE={{.Date}}"
|
||||
- "--build-arg=BUILD_VERSION={{.Version}}"
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
- image_templates:
|
||||
- anchore/syft:{{.Tag}}-nonroot-s390x
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-nonroot-s390x
|
||||
goarch: s390x
|
||||
dockerfile: Dockerfile.nonroot
|
||||
use: buildx
|
||||
build_flag_templates:
|
||||
- "--platform=linux/s390x"
|
||||
- "--build-arg=BUILD_DATE={{.Date}}"
|
||||
- "--build-arg=BUILD_VERSION={{.Version}}"
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
# debug images...
|
||||
- image_templates:
|
||||
- anchore/syft:{{.Tag}}-debug-amd64
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-amd64
|
||||
goarch: amd64
|
||||
dockerfile: Dockerfile.debug
|
||||
use: buildx
|
||||
build_flag_templates:
|
||||
- "--platform=linux/amd64"
|
||||
- "--build-arg=BUILD_DATE={{.Date}}"
|
||||
- "--build-arg=BUILD_VERSION={{.Version}}"
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
- image_templates:
|
||||
- anchore/syft:{{.Tag}}-debug-arm64v8
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-arm64v8
|
||||
goarch: arm64
|
||||
dockerfile: Dockerfile.debug
|
||||
use: buildx
|
||||
build_flag_templates:
|
||||
- "--platform=linux/arm64/v8"
|
||||
- "--build-arg=BUILD_DATE={{.Date}}"
|
||||
- "--build-arg=BUILD_VERSION={{.Version}}"
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
- image_templates:
|
||||
- anchore/syft:{{.Tag}}-debug-ppc64le
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-ppc64le
|
||||
goarch: ppc64le
|
||||
dockerfile: Dockerfile.debug
|
||||
use: buildx
|
||||
build_flag_templates:
|
||||
- "--platform=linux/ppc64le"
|
||||
- "--build-arg=BUILD_DATE={{.Date}}"
|
||||
- "--build-arg=BUILD_VERSION={{.Version}}"
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
- image_templates:
|
||||
- anchore/syft:{{.Tag}}-debug-s390x
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-s390x
|
||||
goarch: s390x
|
||||
dockerfile: Dockerfile.debug
|
||||
use: buildx
|
||||
build_flag_templates:
|
||||
- "--platform=linux/s390x"
|
||||
- "--build-arg=BUILD_DATE={{.Date}}"
|
||||
- "--build-arg=BUILD_VERSION={{.Version}}"
|
||||
- "--build-arg=VCS_REF={{.FullCommit}}"
|
||||
- "--build-arg=VCS_URL={{.GitURL}}"
|
||||
|
||||
docker_manifests:
|
||||
- name_template: anchore/syft:latest
|
||||
image_templates:
|
||||
- anchore/syft:{{.Tag}}-amd64
|
||||
- anchore/syft:{{.Tag}}
|
||||
- anchore/syft:{{.Tag}}-arm64v8
|
||||
- anchore/syft:{{.Tag}}-ppc64le
|
||||
- anchore/syft:{{.Tag}}-s390x
|
||||
|
||||
- name_template: anchore/syft:debug
|
||||
- anchore/syft:{{.Tag}}-debug
|
||||
- anchore/syft:{{.Tag}}-debug-arm64v8
|
||||
- anchore/syft:{{.Tag}}-debug-ppc64le
|
||||
- anchore/syft:{{.Tag}}-debug-s390x
|
||||
|
||||
- name_template: anchore/syft:{{.Tag}}
|
||||
image_templates:
|
||||
- anchore/syft:{{.Tag}}
|
||||
- anchore/syft:{{.Tag}}-arm64v8
|
||||
- anchore/syft:{{.Tag}}-ppc64le
|
||||
- anchore/syft:{{.Tag}}-s390x
|
||||
|
||||
- name_template: ghcr.io/anchore/syft:latest
|
||||
image_templates:
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-amd64
|
||||
- ghcr.io/anchore/syft:{{.Tag}}
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-arm64v8
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-ppc64le
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-s390x
|
||||
|
||||
- name_template: anchore/syft:{{.Tag}}
|
||||
image_templates:
|
||||
- anchore/syft:{{.Tag}}-amd64
|
||||
- anchore/syft:{{.Tag}}-arm64v8
|
||||
- anchore/syft:{{.Tag}}-ppc64le
|
||||
- anchore/syft:{{.Tag}}-s390x
|
||||
|
||||
- name_template: ghcr.io/anchore/syft:{{.Tag}}
|
||||
image_templates:
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-amd64
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-arm64v8
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-ppc64le
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-s390x
|
||||
|
||||
# nonroot images...
|
||||
- name_template: anchore/syft:nonroot
|
||||
image_templates:
|
||||
- anchore/syft:{{.Tag}}-nonroot-amd64
|
||||
- anchore/syft:{{.Tag}}-nonroot-arm64v8
|
||||
- anchore/syft:{{.Tag}}-nonroot-ppc64le
|
||||
- anchore/syft:{{.Tag}}-nonroot-s390x
|
||||
|
||||
- name_template: ghcr.io/anchore/syft:nonroot
|
||||
image_templates:
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-nonroot-amd64
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-nonroot-arm64v8
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-nonroot-ppc64le
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-nonroot-s390x
|
||||
|
||||
- name_template: anchore/syft:{{.Tag}}-nonroot
|
||||
image_templates:
|
||||
- anchore/syft:{{.Tag}}-nonroot-amd64
|
||||
- anchore/syft:{{.Tag}}-nonroot-arm64v8
|
||||
- anchore/syft:{{.Tag}}-nonroot-ppc64le
|
||||
- anchore/syft:{{.Tag}}-nonroot-s390x
|
||||
|
||||
- name_template: ghcr.io/anchore/syft:{{.Tag}}-nonroot
|
||||
image_templates:
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-nonroot-amd64
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-nonroot-arm64v8
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-nonroot-ppc64le
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-nonroot-s390x
|
||||
|
||||
# debug images...
|
||||
- name_template: anchore/syft:debug
|
||||
image_templates:
|
||||
- anchore/syft:{{.Tag}}-debug-amd64
|
||||
- anchore/syft:{{.Tag}}-debug-arm64v8
|
||||
- anchore/syft:{{.Tag}}-debug-ppc64le
|
||||
- anchore/syft:{{.Tag}}-debug-s390x
|
||||
|
||||
- name_template: ghcr.io/anchore/syft:debug
|
||||
image_templates:
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-amd64
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-arm64v8
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-ppc64le
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-s390x
|
||||
|
||||
- name_template: anchore/syft:{{.Tag}}-debug
|
||||
- name_template: ghcr.io/anchore/syft:{{.Tag}}
|
||||
image_templates:
|
||||
- anchore/syft:{{.Tag}}-debug-amd64
|
||||
- anchore/syft:{{.Tag}}-debug-arm64v8
|
||||
- anchore/syft:{{.Tag}}-debug-ppc64le
|
||||
- anchore/syft:{{.Tag}}-debug-s390x
|
||||
|
||||
- name_template: ghcr.io/anchore/syft:{{.Tag}}-debug
|
||||
image_templates:
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-amd64
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-arm64v8
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-ppc64le
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-debug-s390x
|
||||
- ghcr.io/anchore/syft:{{.Tag}}
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-arm64v8
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-ppc64le
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-s390x
|
||||
|
||||
sboms:
|
||||
- artifacts: archive
|
||||
# this is relative to the snapshot/dist directory, not the root of the repo
|
||||
cmd: ../.tool/syft
|
||||
documents:
|
||||
- "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.sbom"
|
||||
|
||||
+1
-5
@@ -8,8 +8,4 @@ A cataloger contributed by Oracle Corporation that extracts packages given withi
|
||||
|
||||
## Swift Package Manager
|
||||
|
||||
A cataloger contributed by Axis Communications that catalogs packages resolved by Swift Package Manager.
|
||||
|
||||
## Bitnami Packages
|
||||
|
||||
A cataloger contributed by Bitnami developer that catalogs packages described in Bitnami SBOMs.
|
||||
A cataloger contributed by Axis Communications that catalogs packages resolved by Swift Package Manager.
|
||||
+3
-13
@@ -227,16 +227,6 @@ rough outline how that works:
|
||||
|
||||
## Testing
|
||||
|
||||
### Testing commands
|
||||
|
||||
* `make help` shows a list of available commands
|
||||
* `make unit`, `make integration`, `make cli`, and `make acceptance` run those test suites (see below)
|
||||
* `make test` runs all those tests (and is therefore pretty slow)
|
||||
* `make fixtures` clears and re-fetches all test fixtures.
|
||||
* `go test ./syft/pkg/` for example can test particular packages, assuming fixtures are already made
|
||||
* `make clean-cache` cleans all test cache. Note that subsequent test runs will be slower after this
|
||||
|
||||
|
||||
### Levels of testing
|
||||
|
||||
- `unit`: The default level of test which is distributed throughout the repo are unit tests. Any `_test.go` file that
|
||||
@@ -377,11 +367,11 @@ package under test and should always be updated by invoking `go test` on the spe
|
||||
update flag provided.
|
||||
|
||||
Many of the `Format` tests make use of this approach, where the raw SBOM report is saved in the repo and the test
|
||||
compares that SBOM with what is generated from the latest presenter code. The following command can be used to
|
||||
update the golden files for the various snapshot tests:
|
||||
compares that SBOM with what is generated from the latest presenter code. For instance, at the time of this writing
|
||||
the CycloneDX presenter snapshots can be updated by running:
|
||||
|
||||
```bash
|
||||
make update-format-golden-files
|
||||
go test ./internal/formats -update-cyclonedx
|
||||
```
|
||||
|
||||
These flags are defined at the top of the test files that have tests that use the snapshot files.
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM gcr.io/distroless/static-debian12:latest AS build
|
||||
FROM gcr.io/distroless/static-debian11:debug@sha256:a0a404776dec98be120089ae42bbdfbe48c177921d856937d124d48eb8c0b951 AS build
|
||||
|
||||
FROM scratch
|
||||
# needed for version check HTTPS request
|
||||
|
||||
+1
-3
@@ -1,12 +1,10 @@
|
||||
FROM gcr.io/distroless/static-debian12:debug-nonroot
|
||||
FROM gcr.io/distroless/static-debian11:debug@sha256:a0a404776dec98be120089ae42bbdfbe48c177921d856937d124d48eb8c0b951
|
||||
|
||||
# create the /tmp dir, which is needed for image content cache
|
||||
WORKDIR /tmp
|
||||
|
||||
COPY syft /
|
||||
|
||||
USER nonroot
|
||||
|
||||
ARG BUILD_DATE
|
||||
ARG BUILD_VERSION
|
||||
ARG VCS_REF
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
FROM gcr.io/distroless/static-debian12:nonroot
|
||||
|
||||
# create the /tmp dir, which is needed for image content cache
|
||||
WORKDIR /tmp
|
||||
|
||||
COPY syft /
|
||||
|
||||
USER nonroot
|
||||
|
||||
ARG BUILD_DATE
|
||||
ARG BUILD_VERSION
|
||||
ARG VCS_REF
|
||||
ARG VCS_URL
|
||||
|
||||
LABEL org.opencontainers.image.created=$BUILD_DATE
|
||||
LABEL org.opencontainers.image.title="syft"
|
||||
LABEL org.opencontainers.image.description="CLI tool and library for generating a Software Bill of Materials from container images and filesystems"
|
||||
LABEL org.opencontainers.image.source=$VCS_URL
|
||||
LABEL org.opencontainers.image.revision=$VCS_REF
|
||||
LABEL org.opencontainers.image.vendor="Anchore, Inc."
|
||||
LABEL org.opencontainers.image.version=$BUILD_VERSION
|
||||
LABEL org.opencontainers.image.licenses="Apache-2.0"
|
||||
LABEL io.artifacthub.package.readme-url="https://raw.githubusercontent.com/anchore/syft/main/README.md"
|
||||
LABEL io.artifacthub.package.logo-url="https://user-images.githubusercontent.com/5199289/136844524-1527b09f-c5cb-4aa9-be54-5aa92a6086c1.png"
|
||||
LABEL io.artifacthub.package.license="Apache-2.0"
|
||||
|
||||
ENTRYPOINT ["/syft"]
|
||||
@@ -12,7 +12,7 @@ TASK = $(TOOL_DIR)/task
|
||||
# note: we need to assume that binny and task have not already been installed
|
||||
$(BINNY):
|
||||
@mkdir -p $(TOOL_DIR)
|
||||
@curl -sSfL https://get.anchore.io/binny | sh -s -- -b $(TOOL_DIR)
|
||||
@curl -sSfL https://raw.githubusercontent.com/$(OWNER)/binny/main/install.sh | sh -s -- -b $(TOOL_DIR)
|
||||
|
||||
# note: we need to assume that binny and task have not already been installed
|
||||
.PHONY: task
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
<a href="https://github.com/anchore/syft" target="_blank"><img alt="GitHub go.mod Go version" src="https://img.shields.io/github/go-mod/go-version/anchore/syft.svg"></a>
|
||||
<a href="" target="_blank"><img alt="License: Apache-2.0" src="https://img.shields.io/badge/License-Apache%202.0-blue.svg"></a>
|
||||
<a href="https://anchore.com/discourse" target="_blank"><img alt="Join our Discourse" src="https://img.shields.io/badge/Discourse-Join-blue?logo=discourse"/></a>
|
||||
<a rel="me" href="https://fosstodon.org/@syft"><img alt="Follow on Mastodon" src="https://img.shields.io/badge/Mastodon-Follow-blue?logoColor=white&logo=mastodon"/></a>
|
||||
</p>
|
||||
|
||||

|
||||
@@ -37,8 +36,8 @@ Syft development is sponsored by [Anchore](https://anchore.com/), and is release
|
||||
Syft binaries are provided for Linux, macOS and Windows.
|
||||
|
||||
### Recommended
|
||||
> ```bash
|
||||
> curl -sSfL https://get.anchore.io/syft | sudo sh -s -- -b /usr/local/bin
|
||||
> ```bash
|
||||
> curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
|
||||
> ```
|
||||
|
||||
Install script options:
|
||||
@@ -67,7 +66,7 @@ choco install syft -y
|
||||
|
||||
### Nix
|
||||
|
||||
**Note**: Nix packaging of Syft is [community maintained](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/sy/syft/package.nix). Syft is available in the [stable channel](https://wiki.nixos.org/wiki/Nix_channels#The_official_channels) since NixOS `22.05`.
|
||||
**Note**: Nix packaging of Syft is [community maintained](https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/admin/syft/default.nix). Syft is available in the [stable channel](https://wiki.nixos.org/wiki/Nix_channels#The_official_channels) since NixOS `22.05`.
|
||||
|
||||
```bash
|
||||
nix-env -i syft
|
||||
@@ -123,7 +122,6 @@ Note that flags using the @<version> can be used for earlier versions of each sp
|
||||
### Supported Ecosystems
|
||||
|
||||
- Alpine (apk)
|
||||
- Bitnami packages
|
||||
- C (conan)
|
||||
- C++ (conan)
|
||||
- Dart (pubs)
|
||||
@@ -140,14 +138,13 @@ Note that flags using the @<version> can be used for earlier versions of each sp
|
||||
- Linux kernel archives (vmlinz)
|
||||
- Linux kernel modules (ko)
|
||||
- Nix (outputs in /nix/store)
|
||||
- PHP (composer, PECL, Pear)
|
||||
- Python (wheel, egg, poetry, requirements.txt, uv)
|
||||
- PHP (composer)
|
||||
- Python (wheel, egg, poetry, requirements.txt)
|
||||
- Red Hat (rpm)
|
||||
- Ruby (gem)
|
||||
- Rust (cargo.lock, auditable binary)
|
||||
- Rust (cargo.lock)
|
||||
- Swift (cocoapods, swift-package-manager)
|
||||
- Wordpress plugins
|
||||
- Terraform providers (.terraform.lock.hcl)
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -157,7 +154,7 @@ Our [wiki](https://github.com/anchore/syft/wiki) contains further details on the
|
||||
* [File Selection](https://github.com/anchore/syft/wiki/file-selection)
|
||||
* [Excluding file paths](https://github.com/anchore/syft/wiki/excluding-file-paths)
|
||||
* [Output formats](https://github.com/anchore/syft/wiki/output-formats)
|
||||
* [Package Cataloger Selection](https://github.com/anchore/syft/wiki/package-cataloger-selection)
|
||||
* [Package Cataloger Selection](https://github.com/anchore/syft/wiki/package-cataloger-selection)
|
||||
* [Concepts](https://github.com/anchore/syft/wiki/package-cataloger-selection#concepts)
|
||||
* [Examples](https://github.com/anchore/syft/wiki/package-cataloger-selection#examples)
|
||||
* [Using templates](https://github.com/anchore/syft/wiki/using-templates)
|
||||
@@ -177,11 +174,7 @@ Check out our [contributing](/CONTRIBUTING.md) guide and [developer](/DEVELOPING
|
||||
|
||||
## Syft Team Meetings
|
||||
|
||||
The Syft Team hold regular community meetings online. All are welcome to join to bring topics for discussion.
|
||||
- Check the [calendar](https://calendar.google.com/calendar/u/0/r?cid=Y182OTM4dGt0MjRtajI0NnNzOThiaGtnM29qNEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t) for the next meeting date.
|
||||
The Syft Team hold regular community meetings online. All are welcome to join to bring topics for discussion.
|
||||
- Check the [calendar](https://calendar.google.com/calendar/u/0/r?cid=Y182OTM4dGt0MjRtajI0NnNzOThiaGtnM29qNEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t) for the next meeting date.
|
||||
- Add items to the [agenda](https://docs.google.com/document/d/1ZtSAa6fj2a6KRWviTn3WoJm09edvrNUp4Iz_dOjjyY8/edit?usp=sharing) (join [this group](https://groups.google.com/g/anchore-oss-community) for write access to the [agenda](https://docs.google.com/document/d/1ZtSAa6fj2a6KRWviTn3WoJm09edvrNUp4Iz_dOjjyY8/edit?usp=sharing))
|
||||
- See you there!
|
||||
|
||||
## Syft Logo
|
||||
|
||||
<p xmlns:cc="http://creativecommons.org/ns#" xmlns:dct="http://purl.org/dc/terms/"><a property="dct:title" rel="cc:attributionURL" href="https://anchore.com/wp-content/uploads/2024/11/syft-logo.svg">Syft Logo</a> by <a rel="cc:attributionURL dct:creator" property="cc:attributionName" href="https://anchore.com/">Anchore</a> is licensed under <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank" rel="license noopener noreferrer" style="display:inline-block;">CC BY 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/cc.svg" alt=""><img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" src="https://mirrors.creativecommons.org/presskit/icons/by.svg" alt=""></a></p>
|
||||
|
||||
+86
-13
@@ -1,16 +1,5 @@
|
||||
# Release
|
||||
|
||||
A release of syft comprises:
|
||||
- a new semver git tag from the current tip of the main branch
|
||||
- a new [github release](https://github.com/anchore/syft/releases) with a changelog and archived binary assets
|
||||
- docker images published to `ghcr.io` and `dockerhub`, including multi architecture images + manifest
|
||||
- [`anchore/homebrew-syft`](https://github.com/anchore/homebrew-syft) tap updated to point to assets in the latest github release
|
||||
|
||||
Ideally releasing should be done often with small increments when possible. Unless a
|
||||
breaking change is blocking the release, or no fixes/features have been merged, a good
|
||||
target release cadence is between every 1 or 2 weeks.
|
||||
|
||||
|
||||
## Creating a release
|
||||
|
||||
This release process itself should be as automated as possible, and has only a few steps:
|
||||
@@ -20,10 +9,16 @@ This release process itself should be as automated as possible, and has only a f
|
||||
you can abort and adjust the labels on the PRs and issues to be included in the release and
|
||||
re-run the release trigger command.
|
||||
|
||||
1. A release admin must approve the release on the GitHub Actions [release pipeline](https://github.com/anchore/syft/actions/workflows/release.yaml) run page.
|
||||
1. A release admin must approve the release on the GitHub Actions release pipeline run page.
|
||||
Once approved, the release pipeline will generate all assets and publish a GitHub Release.
|
||||
|
||||
|
||||
1. If there is a release Milestone, close it.
|
||||
|
||||
Ideally releasing should be done often with small increments when possible. Unless a
|
||||
breaking change is blocking the release, or no fixes/features have been merged, a good
|
||||
target release cadence is between every 1 or 2 weeks.
|
||||
|
||||
|
||||
## Retracting a release
|
||||
|
||||
If a release is found to be problematic, it can be retracted with the following steps:
|
||||
@@ -37,3 +32,81 @@ If a release is found to be problematic, it can be retracted with the following
|
||||
in the go proxy, which will cause confusion when trying to reuse the tag later (the H1 hash will not match and there
|
||||
will be a warning when users try to pull the new release).
|
||||
|
||||
|
||||
## Background
|
||||
|
||||
A good release process has the following qualities:
|
||||
|
||||
1. There is a way to plan what should be in a release
|
||||
1. There is a way to see what is actually in a release
|
||||
1. Allow for different kinds of releases (major breaking vs backwards compatible enhancements vs patch updates)
|
||||
1. Specify a repeatable way to build and publish software artifacts
|
||||
|
||||
|
||||
### Planning a release
|
||||
|
||||
To indicate a set of features to be released together add each issue to an in-repository
|
||||
Milestone named with major-minor version to be released (e.g. `v0.1`). It is OK for other
|
||||
features to be in the release that were not originally planned, and these issues and PRs
|
||||
do not need to be added to the Milestone in question. Only the set of features that, when
|
||||
completed, would allow the release to be considered complete. A Milestone is only used to:
|
||||
|
||||
- Plan what is desired to be in a release
|
||||
- Track progress to indicate when we may be ready to cut a new release
|
||||
|
||||
Not all releases need to be planned. For instance, patch releases for fixes should be
|
||||
released when they are ready and when releasing would not interfere with another current
|
||||
release (where some partial or breaking features have already been merged).
|
||||
|
||||
Unless necessary, feature releases should be small and frequent, which may obviate the
|
||||
need for regular release planning under a Milestone.
|
||||
|
||||
|
||||
### What is in a release
|
||||
|
||||
Milestones are specifically for planning a release, not necessarily tracking all changes
|
||||
that a release may bring (and more importantly, not all releases are necessarily planned
|
||||
either).
|
||||
|
||||
This is one of the (many) reasons for a Changelog. A good Changelog lists changes grouped
|
||||
by the type of change (new, enhancement, deprecation, breaking, bug fix, security fix), in
|
||||
chronological order (within groups), linking the PR where the change was made in the
|
||||
Changelog line. Furthermore, there should be a place to see all released versions, the
|
||||
release date for each release, the semantic version of the release, and the set of changes
|
||||
for each release.
|
||||
|
||||
**This project auto-generates the Changelog contents for each current release and posts the
|
||||
generated contents to the GitHub Release page**. Leveraging the GitHub Releases feature
|
||||
allows GitHub to manage the Changelog on each release outside of the git source tree while
|
||||
still being hosted with the released assets.
|
||||
|
||||
The Changelog is generated from the metadata from in-repository issues and PRs, using
|
||||
labels to guide what kind of change each item is (e.g. breaking, new feature, bug fix,
|
||||
etx). Only issues/PRs with select labels are included in the Changelog, and only if the
|
||||
issue/PR was created after the last release. Additional labels are used to exclude items
|
||||
from the Changelog.
|
||||
|
||||
The above suggestions imply that we should:
|
||||
|
||||
- Ensure there is a sufficient title for each PR and issue title to be included in the
|
||||
Changelog
|
||||
- The appropriate label is applied to PRs and/or issues to drive specific change type
|
||||
sections (deprecated, breaking, security, bug, etc)
|
||||
|
||||
**With this approach as we cultivate good organization of PRs and issues we automatically
|
||||
get an equally good Changelog.**
|
||||
|
||||
|
||||
### Major, minor, and patch releases
|
||||
|
||||
The latest version of the tool is the only supported version, which implies that multiple
|
||||
parallel release branches will not be a regular process (if ever). Multiple releases can
|
||||
be planned in parallel, however, only one can be actively developed at a time. That is, if
|
||||
PRs attached to a release Milestone have been merged into the main branch, that release is
|
||||
now the "next" release. **This implies that the source of truth for release lies with the
|
||||
git log and Changelog, not with the release Milestones** (which are purely for planning and
|
||||
tracking).
|
||||
|
||||
Semantic versioning should be used to indicate breaking changes, new features, and fixes.
|
||||
The exception to this is `< 1.0`, where the major version is not bumped for breaking changes,
|
||||
instead the minor version indicates both new features and breaking changes.
|
||||
|
||||
+66
-54
@@ -27,12 +27,10 @@ vars:
|
||||
sh: uname -s | tr '[:upper:]' '[:lower:]'
|
||||
ARCH:
|
||||
sh: |
|
||||
[ "$(uname -m)" = "x86_64" ] && echo "amd64_v1" || { [ "$(uname -m)" = "aarch64" ] && echo "arm64_v8.0" || [ "$(uname -m)" = "arm64" ] && echo "arm64_v8.0" || echo $(uname -m); }
|
||||
[ "$(uname -m)" = "x86_64" ] && echo "amd64_v1" || echo $(uname -m)
|
||||
PROJECT_ROOT:
|
||||
sh: echo $PWD
|
||||
|
||||
# note: the snapshot dir must be a relative path starting with ./
|
||||
# e.g. when installing snapshot debs from a local path, ./ forces the deb to be installed in the current working directory instead of referencing a package name
|
||||
SNAPSHOT_DIR: ./snapshot
|
||||
SNAPSHOT_BIN: "{{ .PROJECT_ROOT }}/{{ .SNAPSHOT_DIR }}/{{ .OS }}-build_{{ .OS }}_{{ .ARCH }}/{{ .PROJECT }}"
|
||||
SNAPSHOT_CMD: "{{ .TOOL_DIR }}/goreleaser release --config {{ .TMP_DIR }}/goreleaser.yaml --clean --snapshot --skip=publish --skip=sign"
|
||||
@@ -77,8 +75,8 @@ tasks:
|
||||
- task: unit
|
||||
- task: integration
|
||||
- task: validate-cyclonedx-schema
|
||||
- task: benchmark
|
||||
- task: test-utils
|
||||
- task: snapshot
|
||||
- task: cli
|
||||
- task: check-docker-cache
|
||||
|
||||
@@ -91,7 +89,7 @@ tasks:
|
||||
- "{{ .TOOL_DIR }}/binny"
|
||||
status:
|
||||
- "test -f {{ .TOOL_DIR }}/binny"
|
||||
cmd: "curl -sSfL https://get.anchore.io/binny | sh -s -- -b .tool"
|
||||
cmd: "curl -sSfL https://raw.githubusercontent.com/anchore/binny/main/install.sh | sh -s -- -b .tool"
|
||||
silent: true
|
||||
|
||||
tools:
|
||||
@@ -193,14 +191,6 @@ tasks:
|
||||
|
||||
|
||||
## Testing tasks #################################
|
||||
update-format-golden-files:
|
||||
desc: "Update golden (i.e. snapshot) files used by unit tests"
|
||||
cmds:
|
||||
- go test ./syft/format/spdxjson -update-spdx-json
|
||||
- go test ./syft/format/spdxtagvalue -update-spdx-tv
|
||||
- go test ./syft/format/cyclonedxxml -update-cyclonedx-xml
|
||||
- go test ./syft/format/cyclonedxjson -update-cyclonedx-json
|
||||
- go test ./syft/format/syftjson -update-json
|
||||
|
||||
unit:
|
||||
desc: Run unit tests
|
||||
@@ -223,21 +213,24 @@ tasks:
|
||||
cmds:
|
||||
- "go test -v ./cmd/syft/internal/test/integration"
|
||||
# exercise most of the CLI with the data race detector
|
||||
# we use a larger image to ensure we're using multiple catalogers at a time
|
||||
- "go run -race cmd/syft/main.go anchore/test_images:grype-quality-dotnet-69f15d2"
|
||||
- "go run -race cmd/syft/main.go alpine:latest"
|
||||
|
||||
validate-cyclonedx-schema:
|
||||
desc: Validate that Syft produces valid CycloneDX documents
|
||||
desc: Run integration tests
|
||||
cmds:
|
||||
- "cd schema/cyclonedx && make"
|
||||
|
||||
cli:
|
||||
desc: Run CLI tests
|
||||
deps: [tools]
|
||||
# note: we don't want to regenerate the snapshot unless we have to. In CI it's probable
|
||||
# that the cache being restored with the correct binary will be rebuilt since the timestamps
|
||||
# and local checksums will not line up.
|
||||
deps: [tools, snapshot]
|
||||
cmds:
|
||||
- cmd: "echo 'testing binary: {{ .SNAPSHOT_BIN }}'"
|
||||
silent: true
|
||||
- cmd: "test -f {{ .SNAPSHOT_BIN }} || (find {{ .SNAPSHOT_DIR }} && echo '\nno snapshot found for {{ .SNAPSHOT_BIN }}' && false)"
|
||||
|
||||
- cmd: "test -f {{ .SNAPSHOT_BIN }} || (find {{ .SNAPSHOT_DIR }} && echo '\nno snapshot found' && false)"
|
||||
silent: true
|
||||
|
||||
- "go test -count=1 -timeout=15m -v ./test/cli"
|
||||
@@ -250,6 +243,27 @@ tasks:
|
||||
- cmd: .github/scripts/labeler_test.py
|
||||
|
||||
|
||||
## Benchmark test targets #################################
|
||||
|
||||
benchmark:
|
||||
deps: [tmpdir]
|
||||
generates:
|
||||
- "{{ .TMP_DIR }}/benchmark-main.txt"
|
||||
cmds:
|
||||
- "go test -p 1 -run=^Benchmark -bench=. -count=7 -benchmem ./... | tee {{ .TMP_DIR }}/benchmark-{{ .VERSION }}.txt"
|
||||
- |
|
||||
bash -c "(test -s {{ .TMP_DIR }}/benchmark-main.txt && \
|
||||
{{ .TOOL_DIR }}/benchstat {{ .TMP_DIR }}/benchmark-main.txt {{ .TMP_DIR }}/benchmark-{{ .VERSION }}.txt || \
|
||||
{{ .TOOL_DIR }}/benchstat {{ .TMP_DIR }}/benchmark-{{ .VERSION }}.txt) \
|
||||
| tee {{ .TMP_DIR }}/benchstat.txt"
|
||||
|
||||
show-benchstat:
|
||||
deps: [benchmark, tmpdir]
|
||||
cmds:
|
||||
- cmd: "cat {{ .TMP_DIR }}/benchstat.txt"
|
||||
silent: true
|
||||
|
||||
|
||||
## Test-fixture-related targets #################################
|
||||
|
||||
fingerprints:
|
||||
@@ -265,12 +279,12 @@ tasks:
|
||||
YELLOW='\033[0;33m'
|
||||
RESET='\033[0m'
|
||||
|
||||
echo -e "${YELLOW}creating fingerprint files for non-docker fixtures...${RESET}"
|
||||
echo -e "${YELLOW}creating fingerprint files for non-docker fixtures...${RESET}"
|
||||
for dir in $(find . -type d -name 'test-fixtures'); do
|
||||
if [ -f "$dir/Makefile" ]; then
|
||||
# for debugging...
|
||||
#echo -e "${YELLOW}• calculating fingerprints in $dir... ${RESET}"
|
||||
|
||||
|
||||
(make -C "$dir" fingerprint)
|
||||
fi
|
||||
done
|
||||
@@ -299,18 +313,18 @@ tasks:
|
||||
BOLD='\033[1m'
|
||||
PURPLE='\033[0;35m'
|
||||
RESET='\033[0m'
|
||||
|
||||
|
||||
# if DOWNLOAD_TEST_FIXTURE_CACHE is set to 'false', then skip the cache download and always build
|
||||
if [ "$DOWNLOAD_TEST_FIXTURE_CACHE" = "false" ]; then
|
||||
echo -e "${BOLD}${PURPLE}skipping cache download, rebuilding cache...${RESET}"
|
||||
{{ .TASK }} build-fixtures
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
LATEST_FINGERPRINT=$(docker manifest inspect {{ .CACHE_IMAGE }} | {{ .YQ }} -r '.annotations.fingerprint')
|
||||
|
||||
echo "latest cache: $LATEST_FINGERPRINT"
|
||||
|
||||
|
||||
if [ -f {{ .LAST_CACHE_PULL_FILE }} ]; then
|
||||
LAST_PULL_FINGERPRINT=$(cat {{ .LAST_CACHE_PULL_FILE }} | {{ .YQ }} -r '.digest')
|
||||
else
|
||||
@@ -318,41 +332,41 @@ tasks:
|
||||
{{ .TASK }} download-test-fixture-cache
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
{{ .TASK }} fingerprints
|
||||
|
||||
WANT_FINGERPRINT=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.digest')
|
||||
WANT_FINGERPRINT=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.digest')
|
||||
|
||||
echo "desired cache: $WANT_FINGERPRINT"
|
||||
echo "last pulled cache: $LAST_PULL_FINGERPRINT"
|
||||
|
||||
|
||||
# if we already have the latest cache, skip the refresh
|
||||
if [ "$LAST_PULL_FINGERPRINT" = "$WANT_FINGERPRINT" ]; then
|
||||
echo -e "${BOLD}${PURPLE}already have the latest cache (skipping cache download)${RESET}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
# at this point we only refresh the cache if we want the same cache that is currently available.
|
||||
# we don't by default refresh the cache if the cache if it is simply different from what we have,
|
||||
# because we may be working on a code change that doesn't require a cache refresh (but could trigger one,
|
||||
# which would be annoying to deal with in a development workflow).
|
||||
|
||||
|
||||
if [ "$LATEST_FINGERPRINT" = "$WANT_FINGERPRINT" ]; then
|
||||
echo -e "${BOLD}${PURPLE}found newer cache! downloading cache...${RESET}"
|
||||
{{ .TASK }} download-test-fixture-cache
|
||||
else
|
||||
echo -e "${BOLD}${PURPLE}found different cache, but isn't clear if it's newer (skipping cache download and manually building)${RESET}"
|
||||
|
||||
|
||||
{{ .YQ }} eval '.paths[] | "\(.digest) \(.path)"' {{ .LAST_CACHE_PULL_FILE }} > .tmp/last_cache_lines
|
||||
{{ .YQ }} eval '.paths[] | "\(.digest) \(.path)"' {{ .CACHE_PATHS_FILE }} > .tmp/cache_lines
|
||||
diff .tmp/last_cache_lines .tmp/cache_lines || true
|
||||
|
||||
|
||||
echo -e "${BOLD}${PURPLE}diff with more context...${RESET}"
|
||||
|
||||
|
||||
diff -U10000 {{ .LAST_CACHE_PULL_FILE }} {{ .CACHE_PATHS_FILE }} || true
|
||||
|
||||
|
||||
echo -e "${BOLD}${PURPLE}detected changes to input material, manually building fixtures...${RESET}"
|
||||
|
||||
|
||||
{{ .TASK }} build-fixtures
|
||||
fi
|
||||
|
||||
@@ -365,7 +379,7 @@ tasks:
|
||||
BOLD='\033[1m'
|
||||
YELLOW='\033[0;33m'
|
||||
RESET='\033[0m'
|
||||
|
||||
|
||||
# Use a for loop with command substitution to avoid subshell issues
|
||||
for dir in $(find . -type d -name 'test-fixtures'); do
|
||||
if [ -f "$dir/Makefile" ]; then
|
||||
@@ -403,15 +417,15 @@ tasks:
|
||||
set -eu
|
||||
oras_command="{{ .ORAS }} push {{ .CACHE_IMAGE }}"
|
||||
|
||||
paths=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.paths[].path')
|
||||
paths=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.paths[].path')
|
||||
for path in $paths; do
|
||||
oras_command+=" $path"
|
||||
done
|
||||
oras_command+=" {{ .CACHE_PATHS_FILE }}"
|
||||
|
||||
|
||||
oras_command+=" --annotation org.opencontainers.image.source=https://github.com/{{ .OWNER }}/{{ .PROJECT }}"
|
||||
oras_command+=" --annotation fingerprint=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.digest')"
|
||||
|
||||
|
||||
echo "Executing: $oras_command"
|
||||
eval $oras_command
|
||||
|
||||
@@ -430,9 +444,9 @@ tasks:
|
||||
total_size=$(find . | grep cache | grep tar | xargs du -c | grep total | awk '{print $1}')
|
||||
find . | grep cache | grep tar | xargs du
|
||||
echo "total $total_size KB"
|
||||
|
||||
if [ "$total_size" -gt 5242880 ]; then
|
||||
echo 'docker cache is larger than 5GB'
|
||||
|
||||
if [ "$total_size" -gt 1048576 ]; then
|
||||
echo 'docker cache is larger than 1GB'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -552,18 +566,6 @@ tasks:
|
||||
|
||||
- "{{ .SNAPSHOT_CMD }}"
|
||||
|
||||
snapshot-smoke-test:
|
||||
desc: Run a smoke test on the snapshot builds + docker images
|
||||
cmds:
|
||||
- cmd: "echo 'testing snapshot binary: {{ .SNAPSHOT_BIN }}'"
|
||||
silent: true
|
||||
- cmd: "test -f {{ .SNAPSHOT_BIN }} || (find {{ .SNAPSHOT_DIR }} && echo '\nno snapshot found for {{ .SNAPSHOT_BIN }}' && false)"
|
||||
silent: true
|
||||
- "{{ .SNAPSHOT_BIN }} version"
|
||||
- "{{ .SNAPSHOT_BIN }} scan alpine:latest"
|
||||
- docker run --rm anchore/syft:latest version
|
||||
- docker run --rm anchore/syft:latest scan alpine:latest
|
||||
|
||||
changelog:
|
||||
desc: Generate a changelog
|
||||
deps: [tools]
|
||||
@@ -572,7 +574,7 @@ tasks:
|
||||
- "{{ .NEXT_VERSION }}"
|
||||
cmds:
|
||||
- "{{ .TOOL_DIR }}/chronicle -vv -n --version-file {{ .NEXT_VERSION }} > {{ .CHANGELOG }}"
|
||||
- "{{ .TOOL_DIR }}/glow -w 0 {{ .CHANGELOG }}"
|
||||
- "{{ .TOOL_DIR }}/glow {{ .CHANGELOG }}"
|
||||
|
||||
|
||||
## Release targets #################################
|
||||
@@ -604,6 +606,16 @@ tasks:
|
||||
silent: true
|
||||
- "{{ .RELEASE_CMD }}"
|
||||
|
||||
ci-release-version-file:
|
||||
# desc: "[CI only] Update the version file"
|
||||
deps: [tools]
|
||||
cmds:
|
||||
- task: ci-check
|
||||
- ".github/scripts/update-version-file.sh {{ .RELEASE_VERSION }}"
|
||||
requires:
|
||||
vars:
|
||||
- RELEASE_VERSION
|
||||
|
||||
|
||||
## Cleanup targets #################################
|
||||
|
||||
@@ -631,7 +643,7 @@ tasks:
|
||||
BOLD='\033[1m'
|
||||
YELLOW='\033[0;33m'
|
||||
RESET='\033[0m'
|
||||
|
||||
|
||||
# Use a for loop with command substitution to avoid subshell issues
|
||||
for dir in $(find . -type d -name 'test-fixtures'); do
|
||||
if [ -f "$dir/Makefile" ]; then
|
||||
|
||||
+1
-6
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/cmd/syft/internal"
|
||||
"github.com/anchore/syft/cmd/syft/internal/commands"
|
||||
constants "github.com/anchore/syft/internal"
|
||||
)
|
||||
|
||||
// Application constructs the `syft packages` command and aliases the root command to `syft packages`.
|
||||
@@ -48,7 +47,7 @@ func create(id clio.Identification, out io.Writer) (clio.Application, *cobra.Com
|
||||
commands.Cataloger(app),
|
||||
commands.Attest(app),
|
||||
commands.Convert(app),
|
||||
clio.VersionCommand(id, schemaVersion),
|
||||
clio.VersionCommand(id),
|
||||
clio.ConfigCommand(app, nil),
|
||||
cranecmd.NewCmdAuthLogin(id.Name), // syft login uses the same command as crane
|
||||
)
|
||||
@@ -60,7 +59,3 @@ func create(id clio.Identification, out io.Writer) (clio.Application, *cobra.Com
|
||||
|
||||
return app, rootCmd
|
||||
}
|
||||
|
||||
func schemaVersion() (string, any) {
|
||||
return "SchemaVersion", constants.JSONSchemaVersion
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
[TestHandler_handleAttestationStarted/attesting_in_progress/task_line - 1]
|
||||
⠋ Creating a thing running a thing
|
||||
⠋ Creating a thing running a thing
|
||||
---
|
||||
|
||||
[TestHandler_handleAttestationStarted/attesting_in_progress/log - 1]
|
||||
@@ -11,7 +11,7 @@
|
||||
---
|
||||
|
||||
[TestHandler_handleAttestationStarted/attesting_complete/task_line - 1]
|
||||
✔ Created a thing running a thing
|
||||
✔ Created a thing running a thing
|
||||
---
|
||||
|
||||
[TestHandler_handleAttestationStarted/attesting_complete/log - 1]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
[TestHandler_handleFetchImage/fetch_image_in_progress - 1]
|
||||
⠋ Loading image ━━━━━━━━━━━━━━━━━━━━ [current] the-image
|
||||
⠋ Loading image ━━━━━━━━━━━━━━━━━━━━ [current] the-image
|
||||
---
|
||||
|
||||
[TestHandler_handleFetchImage/fetch_image_complete - 1]
|
||||
✔ Loaded image the-image
|
||||
✔ Loaded image the-image
|
||||
---
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
[TestHandler_handleFileIndexingStarted/cataloging_in_progress - 1]
|
||||
⠋ Indexing file system ━━━━━━━━━━━━━━━━━━━━ [current] /some/path
|
||||
⠋ Indexing file system ━━━━━━━━━━━━━━━━━━━━ [current] /some/path
|
||||
---
|
||||
|
||||
[TestHandler_handleFileIndexingStarted/cataloging_complete - 1]
|
||||
✔ Indexed file system /some/path
|
||||
✔ Indexed file system /some/path
|
||||
---
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
[TestHandler_handlePullSourceStarted/snap_download_in_progress - 1]
|
||||
⠋ Downloading snap file... ━━━━━━━━━━━━━━━━━━━━ example-app_1.0_amd64.snap
|
||||
---
|
||||
|
||||
[TestHandler_handlePullSourceStarted/snap_download_complete - 1]
|
||||
✔ Snap downloaded successfully example-app_1.0_amd64.snap
|
||||
---
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
[TestHandler_handleReadImage/read_image_in_progress - 1]
|
||||
⠋ Parsing image ━━━━━━━━━━━━━━━━━━━━ id
|
||||
⠋ Parsing image ━━━━━━━━━━━━━━━━━━━━ id
|
||||
---
|
||||
|
||||
[TestHandler_handleReadImage/read_image_complete - 1]
|
||||
✔ Parsed image id
|
||||
✔ Parsed image id
|
||||
---
|
||||
|
||||
@@ -61,7 +61,7 @@ type backgroundLineReader struct {
|
||||
func (m *Handler) handleAttestationStarted(e partybus.Event) []tea.Model {
|
||||
reader, prog, taskInfo, err := syftEventParsers.ParseAttestationStartedEvent(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ func (cts catalogerTaskModel) View() string {
|
||||
func (m *Handler) handleCatalogerTaskStarted(e partybus.Event) ([]tea.Model, tea.Cmd) {
|
||||
mon, info, err := syftEventParsers.ParseCatalogerTaskStarted(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ func TestHandler_handleCatalogerTaskStarted(t *testing.T) {
|
||||
{
|
||||
name: "cataloging task in progress",
|
||||
eventFn: func(t *testing.T) partybus.Event {
|
||||
value := &monitor.TaskProgress{
|
||||
value := &monitor.CatalogerTaskProgress{
|
||||
AtomicStage: progress.NewAtomicStage("some stage"),
|
||||
Manual: progress.NewManual(100),
|
||||
}
|
||||
@@ -48,7 +48,7 @@ func TestHandler_handleCatalogerTaskStarted(t *testing.T) {
|
||||
{
|
||||
name: "cataloging sub task in progress",
|
||||
eventFn: func(t *testing.T) partybus.Event {
|
||||
value := &monitor.TaskProgress{
|
||||
value := &monitor.CatalogerTaskProgress{
|
||||
AtomicStage: progress.NewAtomicStage("some stage"),
|
||||
Manual: progress.NewManual(100),
|
||||
}
|
||||
@@ -71,7 +71,7 @@ func TestHandler_handleCatalogerTaskStarted(t *testing.T) {
|
||||
{
|
||||
name: "cataloging sub task complete",
|
||||
eventFn: func(t *testing.T) partybus.Event {
|
||||
value := &monitor.TaskProgress{
|
||||
value := &monitor.CatalogerTaskProgress{
|
||||
AtomicStage: progress.NewAtomicStage("some stage"),
|
||||
Manual: progress.NewManual(100),
|
||||
}
|
||||
@@ -94,7 +94,7 @@ func TestHandler_handleCatalogerTaskStarted(t *testing.T) {
|
||||
{
|
||||
name: "cataloging sub task complete -- hide stage",
|
||||
eventFn: func(t *testing.T) partybus.Event {
|
||||
value := &monitor.TaskProgress{
|
||||
value := &monitor.CatalogerTaskProgress{
|
||||
AtomicStage: progress.NewAtomicStage("some stage"),
|
||||
Manual: progress.NewManual(100),
|
||||
}
|
||||
@@ -117,7 +117,7 @@ func TestHandler_handleCatalogerTaskStarted(t *testing.T) {
|
||||
{
|
||||
name: "cataloging sub task complete with removal",
|
||||
eventFn: func(t *testing.T) partybus.Event {
|
||||
value := &monitor.TaskProgress{
|
||||
value := &monitor.CatalogerTaskProgress{
|
||||
AtomicStage: progress.NewAtomicStage("some stage"),
|
||||
Manual: progress.NewManual(100),
|
||||
}
|
||||
@@ -162,7 +162,7 @@ func TestHandler_handleCatalogerTaskStarted(t *testing.T) {
|
||||
}
|
||||
|
||||
// note: this line / event is not under test, only needed to show a sub status
|
||||
kickoffEvent := &monitor.TaskProgress{
|
||||
kickoffEvent := &monitor.CatalogerTaskProgress{
|
||||
AtomicStage: progress.NewAtomicStage(""),
|
||||
Manual: progress.NewManual(-1),
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
func (m *Handler) handleFetchImage(e partybus.Event) []tea.Model {
|
||||
imgName, prog, err := stereoEventParsers.ParseFetchImage(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
func (m *Handler) handleFileIndexingStarted(e partybus.Event) []tea.Model {
|
||||
path, prog, err := syftEventParsers.ParseFileIndexingStarted(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ type containerdPullStatusFormatter struct {
|
||||
func (m *Handler) handlePullContainerdImage(e partybus.Event) []tea.Model {
|
||||
_, pullStatus, err := stereoscopeParsers.ParsePullContainerdImage(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ type dockerPullStatusFormatter struct {
|
||||
func (m *Handler) handlePullDockerImage(e partybus.Event) []tea.Model {
|
||||
_, pullStatus, err := stereoscopeParsers.ParsePullDockerImage(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/wagoodman/go-partybus"
|
||||
|
||||
"github.com/anchore/bubbly/bubbles/taskprogress"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
syftEventParsers "github.com/anchore/syft/syft/event/parsers"
|
||||
)
|
||||
|
||||
func (m *Handler) handlePullSourceStarted(e partybus.Event) []tea.Model {
|
||||
prog, info, err := syftEventParsers.ParsePullSourceStarted(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
tsk := m.newTaskProgress(
|
||||
taskprogress.Title{
|
||||
Default: info.Title.Default,
|
||||
Running: info.Title.WhileRunning,
|
||||
Success: info.Title.OnSuccess,
|
||||
},
|
||||
taskprogress.WithStagedProgressable(prog),
|
||||
)
|
||||
|
||||
tsk.HideOnSuccess = info.HideOnSuccess
|
||||
tsk.HideStageOnSuccess = info.HideStageOnSuccess
|
||||
tsk.HideProgressOnSuccess = true
|
||||
|
||||
if info.Context != "" {
|
||||
tsk.Context = []string{info.Context}
|
||||
}
|
||||
|
||||
return []tea.Model{tsk}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/gkampitakis/go-snaps/snaps"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/wagoodman/go-partybus"
|
||||
"github.com/wagoodman/go-progress"
|
||||
|
||||
"github.com/anchore/bubbly/bubbles/taskprogress"
|
||||
"github.com/anchore/syft/syft/event"
|
||||
"github.com/anchore/syft/syft/event/monitor"
|
||||
)
|
||||
|
||||
func TestHandler_handlePullSourceStarted(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
eventFn func(*testing.T) partybus.Event
|
||||
iterations int
|
||||
}{
|
||||
{
|
||||
name: "snap download in progress",
|
||||
eventFn: func(t *testing.T) partybus.Event {
|
||||
stage := progress.NewAtomicStage("")
|
||||
manual := progress.NewManual(0)
|
||||
manual.SetTotal(1000000) // 1MB file
|
||||
manual.Set(250000) // 25% downloaded
|
||||
|
||||
taskProg := &monitor.TaskProgress{
|
||||
AtomicStage: stage,
|
||||
Manual: manual,
|
||||
}
|
||||
|
||||
genericTask := monitor.GenericTask{
|
||||
Title: monitor.Title{
|
||||
Default: "Downloading snap",
|
||||
WhileRunning: "Downloading snap file...",
|
||||
OnSuccess: "Snap downloaded",
|
||||
},
|
||||
Context: "example-app_1.0_amd64.snap",
|
||||
HideOnSuccess: false,
|
||||
HideStageOnSuccess: true,
|
||||
ID: "snap-download-123",
|
||||
}
|
||||
|
||||
return partybus.Event{
|
||||
Type: event.PullSourceStarted,
|
||||
Source: genericTask,
|
||||
Value: taskProg,
|
||||
}
|
||||
},
|
||||
iterations: 5,
|
||||
},
|
||||
{
|
||||
name: "snap download complete",
|
||||
eventFn: func(t *testing.T) partybus.Event {
|
||||
stage := progress.NewAtomicStage("")
|
||||
manual := progress.NewManual(0)
|
||||
manual.SetTotal(1000000) // 1MB file
|
||||
manual.Set(1000000) // 100% downloaded
|
||||
manual.SetCompleted()
|
||||
|
||||
taskProg := &monitor.TaskProgress{
|
||||
AtomicStage: stage,
|
||||
Manual: manual,
|
||||
}
|
||||
|
||||
genericTask := monitor.GenericTask{
|
||||
Title: monitor.Title{
|
||||
Default: "Downloading snap",
|
||||
WhileRunning: "Downloading snap file...",
|
||||
OnSuccess: "Snap downloaded successfully",
|
||||
},
|
||||
Context: "example-app_1.0_amd64.snap",
|
||||
HideOnSuccess: false,
|
||||
HideStageOnSuccess: true,
|
||||
ID: "snap-download-123",
|
||||
}
|
||||
|
||||
return partybus.Event{
|
||||
Type: event.PullSourceStarted,
|
||||
Source: genericTask,
|
||||
Value: taskProg,
|
||||
}
|
||||
},
|
||||
iterations: 3,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
event := tt.eventFn(t)
|
||||
handler := New(DefaultHandlerConfig())
|
||||
handler.WindowSize = tea.WindowSizeMsg{
|
||||
Width: 100,
|
||||
Height: 80,
|
||||
}
|
||||
|
||||
models := handler.handlePullSourceStarted(event)
|
||||
require.Len(t, models, 1)
|
||||
model := models[0]
|
||||
|
||||
tsk, ok := model.(taskprogress.Model)
|
||||
require.True(t, ok)
|
||||
|
||||
gotModel := runModel(t, tsk, tt.iterations, taskprogress.TickMsg{
|
||||
Time: time.Now(),
|
||||
Sequence: tsk.Sequence(),
|
||||
ID: tsk.ID(),
|
||||
})
|
||||
|
||||
got := gotModel.View()
|
||||
|
||||
t.Log(got)
|
||||
snaps.MatchSnapshot(t, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
func (m *Handler) handleReadImage(e partybus.Event) []tea.Model {
|
||||
imgMetadata, prog, err := stereoEventParsers.ParseReadImage(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Debug("unable to parse event")
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,6 @@ func New(cfg HandlerConfig) *Handler {
|
||||
stereoscopeEvent.FetchImage: simpleHandler(h.handleFetchImage),
|
||||
syftEvent.FileIndexingStarted: simpleHandler(h.handleFileIndexingStarted),
|
||||
syftEvent.AttestationStarted: simpleHandler(h.handleAttestationStarted),
|
||||
syftEvent.PullSourceStarted: simpleHandler(h.handlePullSourceStarted),
|
||||
syftEvent.CatalogerTaskStarted: h.handleCatalogerTaskStarted,
|
||||
})
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/stereoscope"
|
||||
handler "github.com/anchore/syft/cmd/syft/cli/ui"
|
||||
ui2 "github.com/anchore/syft/cmd/syft/cli/ui"
|
||||
"github.com/anchore/syft/cmd/syft/internal/ui"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
@@ -20,18 +20,18 @@ func AppClioSetupConfig(id clio.Identification, out io.Writer) *clio.SetupConfig
|
||||
WithConfigInRootHelp(). // --help on the root command renders the full application config in the help text
|
||||
WithUIConstructor(
|
||||
// select a UI based on the logging configuration and state of stdin (if stdin is a tty)
|
||||
func(cfg clio.Config) (*clio.UICollection, error) {
|
||||
func(cfg clio.Config) ([]clio.UI, error) {
|
||||
noUI := ui.None(out, cfg.Log.Quiet)
|
||||
if !cfg.Log.AllowUI(os.Stdin) || cfg.Log.Quiet {
|
||||
return clio.NewUICollection(noUI), nil
|
||||
return []clio.UI{noUI}, nil
|
||||
}
|
||||
|
||||
return clio.NewUICollection(
|
||||
return []clio.UI{
|
||||
ui.New(out, cfg.Log.Quiet,
|
||||
handler.New(handler.DefaultHandlerConfig()),
|
||||
ui2.New(ui2.DefaultHandlerConfig()),
|
||||
),
|
||||
noUI,
|
||||
), nil
|
||||
}, nil
|
||||
},
|
||||
).
|
||||
WithInitializers(
|
||||
@@ -44,7 +44,7 @@ func AppClioSetupConfig(id clio.Identification, out io.Writer) *clio.SetupConfig
|
||||
redact.Set(state.RedactStore)
|
||||
|
||||
log.Set(state.Logger)
|
||||
stereoscope.SetLogger(state.Logger.Nested("from", "stereoscope"))
|
||||
stereoscope.SetLogger(state.Logger)
|
||||
return nil
|
||||
},
|
||||
).
|
||||
|
||||
@@ -52,7 +52,7 @@ func Attest(app clio.Application) *cobra.Command {
|
||||
opts := defaultAttestOptions()
|
||||
|
||||
// template format explicitly not allowed
|
||||
opts.Template.Enabled = false
|
||||
opts.Format.Template.Enabled = false
|
||||
|
||||
return app.SetupCommand(&cobra.Command{
|
||||
Use: "attest --output [FORMAT] <IMAGE>",
|
||||
@@ -136,7 +136,7 @@ func writeSBOMToFormattedFile(s *sbom.SBOM, sbomFile io.Writer, opts *attestOpti
|
||||
return fmt.Errorf("no output file provided")
|
||||
}
|
||||
|
||||
encs, err := opts.Encoders()
|
||||
encs, err := opts.Format.Encoders()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create encoders: %w", err)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package commands
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -13,18 +12,9 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/cmd/syft/internal/options"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/task"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
)
|
||||
|
||||
var (
|
||||
activelyAddedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("10")) // hi green
|
||||
deselectedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // dark grey
|
||||
activelyRemovedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("9")) // high red
|
||||
defaultStyle = lipgloss.NewStyle().Underline(true)
|
||||
deselectedDefaultStyle = lipgloss.NewStyle().Inherit(deselectedStyle).Underline(true)
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
)
|
||||
|
||||
type catalogerListOptions struct {
|
||||
@@ -54,9 +44,8 @@ func CatalogerList(app clio.Application) *cobra.Command {
|
||||
opts := defaultCatalogerListOptions()
|
||||
|
||||
return app.SetupCommand(&cobra.Command{
|
||||
Use: "list [OPTIONS]",
|
||||
Short: "List available catalogers",
|
||||
PreRunE: disableUI(app, os.Stdout),
|
||||
Use: "list [OPTIONS]",
|
||||
Short: "List available catalogers",
|
||||
RunE: func(_ *cobra.Command, _ []string) error {
|
||||
return runCatalogerList(opts)
|
||||
},
|
||||
@@ -64,19 +53,13 @@ func CatalogerList(app clio.Application) *cobra.Command {
|
||||
}
|
||||
|
||||
func runCatalogerList(opts *catalogerListOptions) error {
|
||||
pkgTaskFactories := task.DefaultPackageTaskFactories()
|
||||
fileTaskFactories := task.DefaultFileTaskFactories()
|
||||
allPkgTasks, err := pkgTaskFactories.Tasks(task.DefaultCatalogingFactoryConfig())
|
||||
factories := task.DefaultPackageTaskFactories()
|
||||
allTasks, err := factories.Tasks(task.DefaultCatalogingFactoryConfig())
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create pkg cataloger tasks: %w", err)
|
||||
return fmt.Errorf("unable to create cataloger tasks: %w", err)
|
||||
}
|
||||
|
||||
allFileTasks, err := fileTaskFactories.Tasks(task.DefaultCatalogingFactoryConfig())
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create file cataloger tasks: %w", err)
|
||||
}
|
||||
|
||||
report, err := catalogerListReport(opts, [][]task.Task{allPkgTasks, allFileTasks})
|
||||
report, err := catalogerListReport(opts, allTasks)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to generate cataloger list report: %w", err)
|
||||
}
|
||||
@@ -86,14 +69,11 @@ func runCatalogerList(opts *catalogerListOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func catalogerListReport(opts *catalogerListOptions, allTaskGroups [][]task.Task) (string, error) {
|
||||
defaultCatalogers := options.Flatten(opts.DefaultCatalogers)
|
||||
selectCatalogers := options.Flatten(opts.SelectCatalogers)
|
||||
selectedTaskGroups, selectionEvidence, err := task.SelectInGroups(
|
||||
allTaskGroups,
|
||||
cataloging.NewSelectionRequest().
|
||||
WithDefaults(defaultCatalogers...).
|
||||
WithExpression(selectCatalogers...),
|
||||
func catalogerListReport(opts *catalogerListOptions, allTasks []task.Task) (string, error) {
|
||||
selectedTasks, selectionEvidence, err := task.Select(allTasks,
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
WithDefaults(opts.DefaultCatalogers...).
|
||||
WithExpression(opts.SelectCatalogers...),
|
||||
)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to select catalogers: %w", err)
|
||||
@@ -102,12 +82,12 @@ func catalogerListReport(opts *catalogerListOptions, allTaskGroups [][]task.Task
|
||||
|
||||
switch opts.Output {
|
||||
case "json":
|
||||
report, err = renderCatalogerListJSON(flattenTaskGroups(selectedTaskGroups), selectionEvidence, defaultCatalogers, selectCatalogers)
|
||||
report, err = renderCatalogerListJSON(selectedTasks, selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
||||
case "table", "":
|
||||
if opts.ShowHidden {
|
||||
report = renderCatalogerListTables(allTaskGroups, selectionEvidence)
|
||||
report = renderCatalogerListTable(allTasks, selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
||||
} else {
|
||||
report = renderCatalogerListTables(selectedTaskGroups, selectionEvidence)
|
||||
report = renderCatalogerListTable(selectedTasks, selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,14 +98,6 @@ func catalogerListReport(opts *catalogerListOptions, allTaskGroups [][]task.Task
|
||||
return report, nil
|
||||
}
|
||||
|
||||
func flattenTaskGroups(taskGroups [][]task.Task) []task.Task {
|
||||
var allTasks []task.Task
|
||||
for _, tasks := range taskGroups {
|
||||
allTasks = append(allTasks, tasks...)
|
||||
}
|
||||
return allTasks
|
||||
}
|
||||
|
||||
func renderCatalogerListJSON(tasks []task.Task, selection task.Selection, defaultSelections, selections []string) (string, error) {
|
||||
type node struct {
|
||||
Name string `json:"name"`
|
||||
@@ -137,12 +109,7 @@ func renderCatalogerListJSON(tasks []task.Task, selection task.Selection, defaul
|
||||
nodesByName := make(map[string]node)
|
||||
|
||||
for name := range tagsByName {
|
||||
tokensByTask, ok := selection.TokensByTask[name]
|
||||
|
||||
var tagsSelected []string
|
||||
if ok {
|
||||
tagsSelected = tokensByTask.SelectedOn.List()
|
||||
}
|
||||
tagsSelected := selection.TokensByTask[name].SelectedOn.List()
|
||||
|
||||
if len(tagsSelected) == 1 && tagsSelected[0] == "all" {
|
||||
tagsSelected = tagsByName[name]
|
||||
@@ -186,56 +153,10 @@ func renderCatalogerListJSON(tasks []task.Task, selection task.Selection, defaul
|
||||
return string(by), err
|
||||
}
|
||||
|
||||
func renderCatalogerListTables(taskGroups [][]task.Task, selection task.Selection) string {
|
||||
pkgCatalogerTable := renderCatalogerListTable(taskGroups[0], selection, "Package Cataloger")
|
||||
fileCatalogerTable := renderCatalogerListTable(taskGroups[1], selection, "File Cataloger")
|
||||
|
||||
report := fileCatalogerTable + "\n" + pkgCatalogerTable + "\n"
|
||||
|
||||
hasAdditions := len(selection.Request.AddNames) > 0
|
||||
hasDefaults := len(selection.Request.DefaultNamesOrTags) > 0
|
||||
hasRemovals := len(selection.Request.RemoveNamesOrTags) > 0
|
||||
hasSubSelections := len(selection.Request.SubSelectTags) > 0
|
||||
expressions := len(selection.Request.SubSelectTags) + len(selection.Request.AddNames) + len(selection.Request.RemoveNamesOrTags)
|
||||
|
||||
var header string
|
||||
|
||||
header += fmt.Sprintf("Default selections: %d\n", len(selection.Request.DefaultNamesOrTags))
|
||||
if hasDefaults {
|
||||
for _, expr := range selection.Request.DefaultNamesOrTags {
|
||||
header += fmt.Sprintf(" • '%s'\n", expr)
|
||||
}
|
||||
}
|
||||
|
||||
header += fmt.Sprintf("Selection expressions: %d\n", expressions)
|
||||
|
||||
if hasSubSelections {
|
||||
for _, n := range selection.Request.SubSelectTags {
|
||||
header += fmt.Sprintf(" • '%s' (intersect)\n", n)
|
||||
}
|
||||
}
|
||||
if hasRemovals {
|
||||
for _, n := range selection.Request.RemoveNamesOrTags {
|
||||
header += fmt.Sprintf(" • '-%s' (remove)\n", n)
|
||||
}
|
||||
}
|
||||
if hasAdditions {
|
||||
for _, n := range selection.Request.AddNames {
|
||||
header += fmt.Sprintf(" • '+%s' (add)\n", n)
|
||||
}
|
||||
}
|
||||
|
||||
return header + report
|
||||
}
|
||||
|
||||
func renderCatalogerListTable(tasks []task.Task, selection task.Selection, kindTitle string) string {
|
||||
if len(tasks) == 0 {
|
||||
return activelyRemovedStyle.Render(fmt.Sprintf("No %ss selected", strings.ToLower(kindTitle)))
|
||||
}
|
||||
|
||||
func renderCatalogerListTable(tasks []task.Task, selection task.Selection, defaultSelections, selections []string) string {
|
||||
t := table.NewWriter()
|
||||
t.SetStyle(table.StyleLight)
|
||||
t.AppendHeader(table.Row{kindTitle, "Tags"})
|
||||
t.AppendHeader(table.Row{"Cataloger", "Tags"})
|
||||
|
||||
names, tagsByName := extractTaskInfo(tasks)
|
||||
|
||||
@@ -251,12 +172,27 @@ func renderCatalogerListTable(tasks []task.Task, selection task.Selection, kindT
|
||||
|
||||
report := t.Render()
|
||||
|
||||
if len(selections) > 0 {
|
||||
header := "Selected by expressions:\n"
|
||||
for _, expr := range selections {
|
||||
header += fmt.Sprintf(" - %q\n", expr)
|
||||
}
|
||||
report = header + report
|
||||
}
|
||||
|
||||
if len(defaultSelections) > 0 {
|
||||
header := "Default selections:\n"
|
||||
for _, expr := range defaultSelections {
|
||||
header += fmt.Sprintf(" - %q\n", expr)
|
||||
}
|
||||
report = header + report
|
||||
}
|
||||
|
||||
return report
|
||||
}
|
||||
|
||||
func formatRow(name string, tags []string, selection task.Selection) table.Row {
|
||||
isIncluded := selection.Result.Has(name)
|
||||
defaults := strset.New(selection.Request.DefaultNamesOrTags...)
|
||||
var selections *task.TokenSelection
|
||||
if s, exists := selection.TokensByTask[name]; exists {
|
||||
selections = &s
|
||||
@@ -264,32 +200,35 @@ func formatRow(name string, tags []string, selection task.Selection) table.Row {
|
||||
|
||||
var formattedTags []string
|
||||
for _, tag := range tags {
|
||||
formattedTags = append(formattedTags, formatToken(tag, selections, isIncluded, defaults))
|
||||
formattedTags = append(formattedTags, formatToken(tag, selections, isIncluded))
|
||||
}
|
||||
|
||||
var tagStr string
|
||||
if isIncluded {
|
||||
tagStr = strings.Join(formattedTags, ", ")
|
||||
} else {
|
||||
tagStr = strings.Join(formattedTags, deselectedStyle.Render(", "))
|
||||
tagStr = strings.Join(formattedTags, grey.Render(", "))
|
||||
}
|
||||
|
||||
// TODO: selection should keep warnings (non-selections) in struct
|
||||
|
||||
return table.Row{
|
||||
formatToken(name, selections, isIncluded, defaults),
|
||||
formatToken(name, selections, isIncluded),
|
||||
tagStr,
|
||||
}
|
||||
}
|
||||
|
||||
func formatToken(token string, selection *task.TokenSelection, included bool, defaults *strset.Set) string {
|
||||
var (
|
||||
green = lipgloss.NewStyle().Foreground(lipgloss.Color("10")) // hi green
|
||||
grey = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // dark grey
|
||||
red = lipgloss.NewStyle().Foreground(lipgloss.Color("9")) // high red
|
||||
)
|
||||
|
||||
func formatToken(token string, selection *task.TokenSelection, included bool) string {
|
||||
if included && selection != nil {
|
||||
// format all tokens in selection in green
|
||||
if selection.SelectedOn.Has(token) {
|
||||
if defaults.Has(token) {
|
||||
return defaultStyle.Render(token)
|
||||
}
|
||||
return activelyAddedStyle.Render(token)
|
||||
return green.Render(token)
|
||||
}
|
||||
|
||||
return token
|
||||
@@ -297,12 +236,10 @@ func formatToken(token string, selection *task.TokenSelection, included bool, de
|
||||
|
||||
// format all tokens in selection in red, all others in grey
|
||||
if selection != nil && selection.DeselectedOn.Has(token) {
|
||||
return activelyRemovedStyle.Render(token)
|
||||
return red.Render(token)
|
||||
}
|
||||
if defaults.Has(token) {
|
||||
return deselectedDefaultStyle.Render(token)
|
||||
}
|
||||
return deselectedStyle.Render(token)
|
||||
|
||||
return grey.Render(token)
|
||||
}
|
||||
|
||||
func extractTaskInfo(tasks []task.Task) ([]string, map[string][]string) {
|
||||
|
||||
@@ -40,35 +40,23 @@ func (d dummyTask) Execute(_ context.Context, _ file.Resolver, _ sbomsync.Builde
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func testTasks() [][]task.Task {
|
||||
return [][]task.Task{
|
||||
{
|
||||
dummyTask{
|
||||
name: "task1",
|
||||
selectors: []string{"image", "a", "b", "1"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task2",
|
||||
selectors: []string{"image", "b", "c", "2"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task3",
|
||||
selectors: []string{"directory", "c", "d", "3"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task4",
|
||||
selectors: []string{"directory", "d", "e", "4"},
|
||||
},
|
||||
func testTasks() []task.Task {
|
||||
return []task.Task{
|
||||
dummyTask{
|
||||
name: "task1",
|
||||
selectors: []string{"image", "a", "b", "1"},
|
||||
},
|
||||
{
|
||||
dummyTask{
|
||||
name: "file-task1",
|
||||
selectors: []string{"file", "ft", "ft-1-b"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "file-task2",
|
||||
selectors: []string{"file", "ft", "ft-2-b"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task2",
|
||||
selectors: []string{"image", "b", "c", "2"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task3",
|
||||
selectors: []string{"directory", "c", "d", "3"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task4",
|
||||
selectors: []string{"directory", "d", "e", "4"},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -88,23 +76,16 @@ func Test_catalogerListReport(t *testing.T) {
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
Default selections: 1
|
||||
• 'all'
|
||||
Selection expressions: 0
|
||||
┌────────────────┬──────────────────┐
|
||||
│ FILE CATALOGER │ TAGS │
|
||||
├────────────────┼──────────────────┤
|
||||
│ file-task1 │ file, ft, ft-1-b │
|
||||
│ file-task2 │ file, ft, ft-2-b │
|
||||
└────────────────┴──────────────────┘
|
||||
┌───────────────────┬────────────────────┐
|
||||
│ PACKAGE CATALOGER │ TAGS │
|
||||
├───────────────────┼────────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task2 │ 2, b, c, image │
|
||||
│ task3 │ 3, c, d, directory │
|
||||
│ task4 │ 4, d, directory, e │
|
||||
└───────────────────┴────────────────────┘
|
||||
Default selections:
|
||||
- "all"
|
||||
┌───────────┬────────────────────┐
|
||||
│ CATALOGER │ TAGS │
|
||||
├───────────┼────────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task2 │ 2, b, c, image │
|
||||
│ task3 │ 3, c, d, directory │
|
||||
│ task4 │ 4, d, directory, e │
|
||||
└───────────┴────────────────────┘
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -115,7 +96,7 @@ Selection expressions: 0
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
{"default":["all"],"selection":[],"catalogers":[{"name":"file-task1","tags":["file","ft","ft-1-b"]},{"name":"file-task2","tags":["file","ft","ft-2-b"]},{"name":"task1","tags":["1","a","b","image"]},{"name":"task2","tags":["2","b","c","image"]},{"name":"task3","tags":["3","c","d","directory"]},{"name":"task4","tags":["4","d","directory","e"]}]}
|
||||
{"default":["all"],"selection":[],"catalogers":[{"name":"task1","tags":["1","a","b","image"]},{"name":"task2","tags":["2","b","c","image"]},{"name":"task3","tags":["3","c","d","directory"]},{"name":"task4","tags":["4","d","directory","e"]}]}
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -124,27 +105,19 @@ Selection expressions: 0
|
||||
c := defaultCatalogerListOptions()
|
||||
c.Output = "table"
|
||||
c.DefaultCatalogers = []string{
|
||||
"image", // note: for backwards compatibility file will automatically be added
|
||||
"image",
|
||||
}
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
Default selections: 2
|
||||
• 'image'
|
||||
• 'file'
|
||||
Selection expressions: 0
|
||||
┌────────────────┬──────────────────┐
|
||||
│ FILE CATALOGER │ TAGS │
|
||||
├────────────────┼──────────────────┤
|
||||
│ file-task1 │ file, ft, ft-1-b │
|
||||
│ file-task2 │ file, ft, ft-2-b │
|
||||
└────────────────┴──────────────────┘
|
||||
┌───────────────────┬────────────────┐
|
||||
│ PACKAGE CATALOGER │ TAGS │
|
||||
├───────────────────┼────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task2 │ 2, b, c, image │
|
||||
└───────────────────┴────────────────┘
|
||||
Default selections:
|
||||
- "image"
|
||||
┌───────────┬────────────────┐
|
||||
│ CATALOGER │ TAGS │
|
||||
├───────────┼────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task2 │ 2, b, c, image │
|
||||
└───────────┴────────────────┘
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -158,7 +131,7 @@ Selection expressions: 0
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
{"default":["image"],"selection":[],"catalogers":[{"name":"file-task1","tags":["file"]},{"name":"file-task2","tags":["file"]},{"name":"task1","tags":["image"]},{"name":"task2","tags":["image"]}]}
|
||||
{"default":["image"],"selection":[],"catalogers":[{"name":"task1","tags":["image"]},{"name":"task2","tags":["image"]}]}
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -174,69 +147,23 @@ Selection expressions: 0
|
||||
"+task3",
|
||||
"-c",
|
||||
"b",
|
||||
"-file",
|
||||
"+file-task1",
|
||||
}
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
Default selections: 1
|
||||
• 'image'
|
||||
Selection expressions: 6
|
||||
• 'b' (intersect)
|
||||
• '-c' (remove)
|
||||
• '-directory' (remove)
|
||||
• '-file' (remove)
|
||||
• '+file-task1' (add)
|
||||
• '+task3' (add)
|
||||
┌────────────────┬──────────────────┐
|
||||
│ FILE CATALOGER │ TAGS │
|
||||
├────────────────┼──────────────────┤
|
||||
│ file-task1 │ file, ft, ft-1-b │
|
||||
└────────────────┴──────────────────┘
|
||||
┌───────────────────┬────────────────────┐
|
||||
│ PACKAGE CATALOGER │ TAGS │
|
||||
├───────────────────┼────────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task3 │ 3, c, d, directory │
|
||||
└───────────────────┴────────────────────┘
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "with comma separated expressions, table",
|
||||
options: func() *catalogerListOptions {
|
||||
c := defaultCatalogerListOptions()
|
||||
c.Output = "table"
|
||||
c.DefaultCatalogers = []string{
|
||||
"image,task3,file-task1",
|
||||
}
|
||||
c.SelectCatalogers = []string{
|
||||
"-task2,c,b",
|
||||
}
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
Default selections: 4
|
||||
• 'file-task1'
|
||||
• 'image'
|
||||
• 'task3'
|
||||
• 'file'
|
||||
Selection expressions: 3
|
||||
• 'b' (intersect)
|
||||
• 'c' (intersect)
|
||||
• '-task2' (remove)
|
||||
┌────────────────┬──────────────────┐
|
||||
│ FILE CATALOGER │ TAGS │
|
||||
├────────────────┼──────────────────┤
|
||||
│ file-task1 │ file, ft, ft-1-b │
|
||||
│ file-task2 │ file, ft, ft-2-b │
|
||||
└────────────────┴──────────────────┘
|
||||
┌───────────────────┬────────────────────┐
|
||||
│ PACKAGE CATALOGER │ TAGS │
|
||||
├───────────────────┼────────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task3 │ 3, c, d, directory │
|
||||
└───────────────────┴────────────────────┘
|
||||
Default selections:
|
||||
- "image"
|
||||
Selected by expressions:
|
||||
- "-directory"
|
||||
- "+task3"
|
||||
- "-c"
|
||||
- "b"
|
||||
┌───────────┬────────────────────┐
|
||||
│ CATALOGER │ TAGS │
|
||||
├───────────┼────────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task3 │ 3, c, d, directory │
|
||||
└───────────┴────────────────────┘
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -256,7 +183,7 @@ Selection expressions: 3
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
{"default":["image"],"selection":["+task3","-c","-directory","b"],"catalogers":[{"name":"file-task1","tags":["file"]},{"name":"file-task2","tags":["file"]},{"name":"task1","tags":["b","image"]},{"name":"task3","tags":["task3"]}]}
|
||||
{"default":["image"],"selection":["-directory","+task3","-c","b"],"catalogers":[{"name":"task1","tags":["b","image"]},{"name":"task3","tags":["task3"]}]}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
|
||||
const (
|
||||
convertExample = ` {{.appName}} {{.command}} img.syft.json -o spdx-json convert a syft SBOM to spdx-json, output goes to stdout
|
||||
{{.appName}} {{.command}} img.syft.json -o cyclonedx-json=img.cdx.json convert a syft SBOM to CycloneDX, output is written to the file "img.cdx.json"
|
||||
{{.appName}} {{.command}} img.syft.json -o cyclonedx-json=img.cdx.json convert a syft SBOM to CycloneDX, output is written to the file "img.cdx.json""
|
||||
{{.appName}} {{.command}} - -o spdx-json convert an SBOM from STDIN to spdx-json
|
||||
`
|
||||
)
|
||||
@@ -39,7 +39,7 @@ func Convert(app clio.Application) *cobra.Command {
|
||||
return app.SetupCommand(&cobra.Command{
|
||||
Use: "convert [SOURCE-SBOM] -o [FORMAT]",
|
||||
Short: "Convert between SBOM formats",
|
||||
Long: "[Experimental] Convert SBOM files to, and from, SPDX, CycloneDX and Syft's format. For more info about data loss between formats see https://github.com/anchore/syft/wiki/format-conversion",
|
||||
Long: "[Experimental] Convert SBOM files to, and from, SPDX, CycloneDX and Syft's format. For more info about data loss between formats see https://github.com/anchore/syft#format-conversion-experimental",
|
||||
Example: internal.Tprintf(convertExample, map[string]interface{}{
|
||||
"appName": id.Name,
|
||||
"command": "convert",
|
||||
|
||||
@@ -10,10 +10,9 @@ import (
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/spf13/cobra"
|
||||
"go.yaml.in/yaml/v3"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/fangs"
|
||||
"github.com/anchore/go-collections"
|
||||
"github.com/anchore/stereoscope"
|
||||
"github.com/anchore/stereoscope/pkg/image"
|
||||
@@ -110,7 +109,7 @@ func (o *scanOptions) PostLoad() error {
|
||||
}
|
||||
|
||||
func (o *scanOptions) validateLegacyOptionsNotUsed() error {
|
||||
if len(fangs.Flatten(o.ConfigFile)) == 0 {
|
||||
if o.Config.ConfigFile == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -122,33 +121,32 @@ func (o *scanOptions) validateLegacyOptionsNotUsed() error {
|
||||
File any `yaml:"file" json:"file" mapstructure:"file"`
|
||||
}
|
||||
|
||||
for _, f := range fangs.Flatten(o.ConfigFile) {
|
||||
by, err := os.ReadFile(f)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read config file during validations %q: %w", f, err)
|
||||
}
|
||||
|
||||
var legacy legacyConfig
|
||||
if err := yaml.Unmarshal(by, &legacy); err != nil {
|
||||
return fmt.Errorf("unable to parse config file during validations %q: %w", f, err)
|
||||
}
|
||||
|
||||
if legacy.DefaultImagePullSource != nil {
|
||||
return fmt.Errorf("the config file option 'default-image-pull-source' has been removed, please use 'source.image.default-pull-source' instead")
|
||||
}
|
||||
|
||||
if legacy.ExcludeBinaryOverlapByOwnership != nil {
|
||||
return fmt.Errorf("the config file option 'exclude-binary-overlap-by-ownership' has been removed, please use 'package.exclude-binary-overlap-by-ownership' instead")
|
||||
}
|
||||
|
||||
if legacy.BasePath != nil {
|
||||
return fmt.Errorf("the config file option 'base-path' has been removed, please use 'source.base-path' instead")
|
||||
}
|
||||
|
||||
if legacy.File != nil && reflect.TypeOf(legacy.File).Kind() == reflect.String {
|
||||
return fmt.Errorf("the config file option 'file' has been removed, please use 'outputs' instead")
|
||||
}
|
||||
by, err := os.ReadFile(o.Config.ConfigFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read config file during validations %q: %w", o.Config.ConfigFile, err)
|
||||
}
|
||||
|
||||
var legacy legacyConfig
|
||||
if err := yaml.Unmarshal(by, &legacy); err != nil {
|
||||
return fmt.Errorf("unable to parse config file during validations %q: %w", o.Config.ConfigFile, err)
|
||||
}
|
||||
|
||||
if legacy.DefaultImagePullSource != nil {
|
||||
return fmt.Errorf("the config file option 'default-image-pull-source' has been removed, please use 'source.image.default-pull-source' instead")
|
||||
}
|
||||
|
||||
if legacy.ExcludeBinaryOverlapByOwnership != nil {
|
||||
return fmt.Errorf("the config file option 'exclude-binary-overlap-by-ownership' has been removed, please use 'package.exclude-binary-overlap-by-ownership' instead")
|
||||
}
|
||||
|
||||
if legacy.BasePath != nil {
|
||||
return fmt.Errorf("the config file option 'base-path' has been removed, please use 'source.base-path' instead")
|
||||
}
|
||||
|
||||
if legacy.File != nil && reflect.TypeOf(legacy.File).Kind() == reflect.String {
|
||||
return fmt.Errorf("the config file option 'file' has been removed, please use 'outputs' instead")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -156,13 +154,13 @@ func validateScanArgs(cmd *cobra.Command, args []string) error {
|
||||
return validateArgs(cmd, args, "an image/directory argument is required")
|
||||
}
|
||||
|
||||
func validateArgs(cmd *cobra.Command, args []string, err string) error {
|
||||
func validateArgs(cmd *cobra.Command, args []string, error string) error {
|
||||
if len(args) == 0 {
|
||||
// in the case that no arguments are given we want to show the help text and return with a non-0 return code.
|
||||
if err := cmd.Help(); err != nil {
|
||||
return fmt.Errorf("unable to display help: %w", err)
|
||||
}
|
||||
return fmt.Errorf("%v", err)
|
||||
return fmt.Errorf("%v", error)
|
||||
}
|
||||
|
||||
return cobra.MaximumNArgs(1)(cmd, args)
|
||||
@@ -218,9 +216,8 @@ func getSource(ctx context.Context, opts *options.Catalog, userInput string, sou
|
||||
cfg := syft.DefaultGetSourceConfig().
|
||||
WithRegistryOptions(opts.Registry.ToOptions()).
|
||||
WithAlias(source.Alias{
|
||||
Name: opts.Source.Name,
|
||||
Version: opts.Source.Version,
|
||||
Supplier: opts.Source.Supplier,
|
||||
Name: opts.Source.Name,
|
||||
Version: opts.Source.Version,
|
||||
}).
|
||||
WithExcludeConfig(source.ExcludeConfig{
|
||||
Paths: opts.Exclusions,
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/cmd/syft/internal/ui"
|
||||
)
|
||||
|
||||
func disableUI(app clio.Application, out io.Writer) func(*cobra.Command, []string) error {
|
||||
return func(_ *cobra.Command, _ []string) error {
|
||||
type Stater interface {
|
||||
State() *clio.State
|
||||
}
|
||||
|
||||
state := app.(Stater).State()
|
||||
state.UI = clio.NewUICollection(ui.None(out, state.Config.Log.Quiet))
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/adrg/xdg"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/go-homedir"
|
||||
"github.com/anchore/syft/internal/cache"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
)
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/adrg/xdg"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/go-homedir"
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/internal/cache"
|
||||
)
|
||||
@@ -57,13 +57,35 @@ func Test_defaultDir(t *testing.T) {
|
||||
env[k] = os.Getenv(k)
|
||||
}
|
||||
|
||||
unsetEnv := func(t *testing.T) {
|
||||
for k := range env {
|
||||
t.Setenv(k, "")
|
||||
}
|
||||
}
|
||||
|
||||
resetEnv := func() {
|
||||
for k, v := range env {
|
||||
if v == "" {
|
||||
_ = os.Unsetenv(k)
|
||||
} else {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
homedir.Reset()
|
||||
xdg.Reload()
|
||||
}
|
||||
|
||||
t.Cleanup(resetEnv)
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
restoreCache(t)
|
||||
defer resetEnv()
|
||||
|
||||
unsetEnv(t)
|
||||
for k, v := range test.env {
|
||||
patchEnv(t, k, v)
|
||||
t.Setenv(k, v)
|
||||
}
|
||||
homedir.Reset()
|
||||
xdg.Reload()
|
||||
|
||||
got := defaultDir()
|
||||
@@ -289,35 +311,3 @@ func Test_durationToString(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// restoreCache ensures cache settings are restored after test
|
||||
func restoreCache(t testing.TB) {
|
||||
t.Helper()
|
||||
origEnabled := homedir.CacheEnabled()
|
||||
|
||||
t.Cleanup(func() {
|
||||
homedir.SetCacheEnable(origEnabled)
|
||||
homedir.Reset()
|
||||
})
|
||||
}
|
||||
|
||||
// patchEnv modifies an environment variable for the duration of the test
|
||||
func patchEnv(t testing.TB, key, value string) {
|
||||
t.Helper()
|
||||
original := os.Getenv(key)
|
||||
|
||||
if value != "" {
|
||||
os.Setenv(key, value)
|
||||
} else {
|
||||
os.Unsetenv(key)
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
if original != "" {
|
||||
os.Setenv(key, original)
|
||||
} else {
|
||||
os.Unsetenv(key)
|
||||
}
|
||||
xdg.Reload()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -19,12 +19,10 @@ import (
|
||||
"github.com/anchore/syft/syft/file/cataloger/executable"
|
||||
"github.com/anchore/syft/syft/file/cataloger/filecontent"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/binary"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/golang"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/kernel"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/nix"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/python"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
@@ -35,7 +33,6 @@ type Catalog struct {
|
||||
DefaultCatalogers []string `yaml:"default-catalogers" json:"default-catalogers" mapstructure:"default-catalogers"`
|
||||
SelectCatalogers []string `yaml:"select-catalogers" json:"select-catalogers" mapstructure:"select-catalogers"`
|
||||
Package packageConfig `yaml:"package" json:"package" mapstructure:"package"`
|
||||
License licenseConfig `yaml:"license" json:"license" mapstructure:"license"`
|
||||
File fileConfig `yaml:"file" json:"file" mapstructure:"file"`
|
||||
Scope string `yaml:"scope" json:"scope" mapstructure:"scope"`
|
||||
Parallelism int `yaml:"parallelism" json:"parallelism" mapstructure:"parallelism"` // the number of catalog workers to run in parallel
|
||||
@@ -44,12 +41,10 @@ type Catalog struct {
|
||||
Enrich []string `yaml:"enrich" json:"enrich" mapstructure:"enrich"`
|
||||
|
||||
// ecosystem-specific cataloger configuration
|
||||
Dotnet dotnetConfig `yaml:"dotnet" json:"dotnet" mapstructure:"dotnet"`
|
||||
Golang golangConfig `yaml:"golang" json:"golang" mapstructure:"golang"`
|
||||
Java javaConfig `yaml:"java" json:"java" mapstructure:"java"`
|
||||
JavaScript javaScriptConfig `yaml:"javascript" json:"javascript" mapstructure:"javascript"`
|
||||
LinuxKernel linuxKernelConfig `yaml:"linux-kernel" json:"linux-kernel" mapstructure:"linux-kernel"`
|
||||
Nix nixConfig `yaml:"nix" json:"nix" mapstructure:"nix"`
|
||||
Python pythonConfig `yaml:"python" json:"python" mapstructure:"python"`
|
||||
|
||||
// configuration for the source (the subject being analyzed)
|
||||
@@ -58,9 +53,6 @@ type Catalog struct {
|
||||
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"`
|
||||
Source sourceConfig `yaml:"source" json:"source" mapstructure:"source"`
|
||||
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
|
||||
|
||||
// configuration for inclusion of unknown information within elements
|
||||
Unknowns unknownsConfig `yaml:"unknowns" mapstructure:"unknowns"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
@@ -70,22 +62,17 @@ var _ interface {
|
||||
} = (*Catalog)(nil)
|
||||
|
||||
func DefaultCatalog() Catalog {
|
||||
cfg := syft.DefaultCreateSBOMConfig()
|
||||
return Catalog{
|
||||
Compliance: defaultComplianceConfig(),
|
||||
Scope: source.SquashedScope.String(),
|
||||
Package: defaultPackageConfig(),
|
||||
License: defaultLicenseConfig(),
|
||||
LinuxKernel: defaultLinuxKernelConfig(),
|
||||
Nix: defaultNixConfig(),
|
||||
Dotnet: defaultDotnetConfig(),
|
||||
Golang: defaultGolangConfig(),
|
||||
Java: defaultJavaConfig(),
|
||||
File: defaultFileConfig(),
|
||||
Relationships: defaultRelationshipsConfig(),
|
||||
Unknowns: defaultUnknowns(),
|
||||
Source: defaultSourceConfig(),
|
||||
Parallelism: cfg.Parallelism,
|
||||
Parallelism: 1,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,13 +82,11 @@ func (cfg Catalog) ToSBOMConfig(id clio.Identification) *syft.CreateSBOMConfig {
|
||||
WithParallelism(cfg.Parallelism).
|
||||
WithRelationshipsConfig(cfg.ToRelationshipsConfig()).
|
||||
WithComplianceConfig(cfg.ToComplianceConfig()).
|
||||
WithUnknownsConfig(cfg.ToUnknownsConfig()).
|
||||
WithSearchConfig(cfg.ToSearchConfig()).
|
||||
WithPackagesConfig(cfg.ToPackagesConfig()).
|
||||
WithLicenseConfig(cfg.ToLicenseConfig()).
|
||||
WithFilesConfig(cfg.ToFilesConfig()).
|
||||
WithCatalogerSelection(
|
||||
cataloging.NewSelectionRequest().
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
WithDefaults(cfg.DefaultCatalogers...).
|
||||
WithExpression(cfg.SelectCatalogers...),
|
||||
)
|
||||
@@ -129,13 +114,6 @@ func (cfg Catalog) ToComplianceConfig() cataloging.ComplianceConfig {
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg Catalog) ToUnknownsConfig() cataloging.UnknownsConfig {
|
||||
return cataloging.UnknownsConfig{
|
||||
IncludeExecutablesWithoutPackages: cfg.Unknowns.ExecutablesWithoutPackages,
|
||||
IncludeUnexpandedArchives: cfg.Unknowns.UnexpandedArchives,
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg Catalog) ToFilesConfig() filecataloging.Config {
|
||||
hashers, err := intFile.Hashers(cfg.File.Metadata.Digests...)
|
||||
if err != nil {
|
||||
@@ -156,13 +134,6 @@ func (cfg Catalog) ToFilesConfig() filecataloging.Config {
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg Catalog) ToLicenseConfig() cataloging.LicenseConfig {
|
||||
return cataloging.LicenseConfig{
|
||||
IncludeContent: cfg.License.Content,
|
||||
Coverage: cfg.License.Coverage,
|
||||
}
|
||||
}
|
||||
|
||||
func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
||||
archiveSearch := cataloging.ArchiveSearchConfig{
|
||||
IncludeIndexedArchives: cfg.Package.SearchIndexedArchives,
|
||||
@@ -170,16 +141,9 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
||||
}
|
||||
return pkgcataloging.Config{
|
||||
Binary: binary.DefaultClassifierCatalogerConfig(),
|
||||
Dotnet: dotnet.DefaultCatalogerConfig().
|
||||
WithDepPackagesMustHaveDLL(cfg.Dotnet.DepPackagesMustHaveDLL).
|
||||
WithDepPackagesMustClaimDLL(cfg.Dotnet.DepPackagesMustClaimDLL).
|
||||
WithPropagateDLLClaimsToParents(cfg.Dotnet.PropagateDLLClaimsToParents).
|
||||
WithRelaxDLLClaimsWhenBundlingDetected(cfg.Dotnet.RelaxDLLClaimsWhenBundlingDetected),
|
||||
Golang: golang.DefaultCatalogerConfig().
|
||||
WithSearchLocalModCacheLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Go, task.Golang), cfg.Golang.SearchLocalModCacheLicenses)).
|
||||
WithLocalModCacheDir(cfg.Golang.LocalModCacheDir).
|
||||
WithSearchLocalVendorLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Go, task.Golang), cfg.Golang.SearchLocalVendorLicenses)).
|
||||
WithLocalVendorDir(cfg.Golang.LocalVendorDir).
|
||||
WithSearchRemoteLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Go, task.Golang), cfg.Golang.SearchRemoteLicenses)).
|
||||
WithProxy(cfg.Golang.Proxy).
|
||||
WithNoProxy(cfg.Golang.NoProxy).
|
||||
@@ -190,14 +154,11 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
||||
WithFromLDFlags(cfg.Golang.MainModuleVersion.FromLDFlags),
|
||||
),
|
||||
JavaScript: javascript.DefaultCatalogerConfig().
|
||||
WithIncludeDevDependencies(*multiLevelOption(false, cfg.JavaScript.IncludeDevDependencies)).
|
||||
WithSearchRemoteLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.JavaScript, task.Node, task.NPM), cfg.JavaScript.SearchRemoteLicenses)).
|
||||
WithNpmBaseURL(cfg.JavaScript.NpmBaseURL),
|
||||
LinuxKernel: kernel.LinuxKernelCatalogerConfig{
|
||||
CatalogModules: cfg.LinuxKernel.CatalogModules,
|
||||
},
|
||||
Nix: nix.DefaultConfig().
|
||||
WithCaptureOwnedFiles(cfg.Nix.CaptureOwnedFiles),
|
||||
Python: python.CatalogerConfig{
|
||||
GuessUnpinnedRequirements: cfg.Python.GuessUnpinnedRequirements,
|
||||
},
|
||||
@@ -206,8 +167,7 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
||||
WithMavenLocalRepositoryDir(cfg.Java.MavenLocalRepositoryDir).
|
||||
WithUseNetwork(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Java, task.Maven), cfg.Java.UseNetwork)).
|
||||
WithMavenBaseURL(cfg.Java.MavenURL).
|
||||
WithArchiveTraversal(archiveSearch, cfg.Java.MaxParentRecursiveDepth).
|
||||
WithResolveTransitiveDependencies(cfg.Java.ResolveTransitiveDependencies),
|
||||
WithArchiveTraversal(archiveSearch, cfg.Java.MaxParentRecursiveDepth),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,9 +191,6 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
|
||||
flags.StringArrayVarP(&cfg.Catalogers, "catalogers", "",
|
||||
"enable one or more package catalogers")
|
||||
|
||||
flags.IntVarP(&cfg.Parallelism, "parallelism", "",
|
||||
"number of cataloger workers to run in parallel")
|
||||
|
||||
if pfp, ok := flags.(fangs.PFlagSetProvider); ok {
|
||||
if err := pfp.PFlagSet().MarkDeprecated("catalogers", "use: override-default-catalogers and select-catalogers"); err != nil {
|
||||
panic(err)
|
||||
@@ -259,14 +216,10 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
|
||||
|
||||
flags.StringVarP(&cfg.Source.BasePath, "base-path", "",
|
||||
"base directory for scanning, no links will be followed above this directory, and all paths will be reported relative to this directory")
|
||||
|
||||
flags.StringVarP(&cfg.Source.Supplier, "source-supplier", "",
|
||||
"the organization that supplied the component, which often may be the manufacturer, distributor, or repackager")
|
||||
}
|
||||
|
||||
func (cfg *Catalog) DescribeFields(descriptions fangs.FieldDescriptionSet) {
|
||||
descriptions.Add(&cfg.Parallelism, `number of cataloger workers to run in parallel
|
||||
by default, when set to 0: this will be based on runtime.NumCPU * 4, if set to less than 0 it will be unbounded`)
|
||||
descriptions.Add(&cfg.Parallelism, "number of cataloger workers to run in parallel")
|
||||
|
||||
descriptions.Add(&cfg.Enrich, fmt.Sprintf(`Enable data enrichment operations, which can utilize services such as Maven Central and NPM.
|
||||
By default all enrichment is disabled, use: all to enable everything.
|
||||
@@ -281,12 +234,12 @@ func (cfg *Catalog) PostLoad() error {
|
||||
return fmt.Errorf("cannot use both 'catalogers' and 'select-catalogers'/'default-catalogers' flags")
|
||||
}
|
||||
|
||||
cfg.From = Flatten(cfg.From)
|
||||
cfg.From = flatten(cfg.From)
|
||||
|
||||
cfg.Catalogers = Flatten(cfg.Catalogers)
|
||||
cfg.DefaultCatalogers = Flatten(cfg.DefaultCatalogers)
|
||||
cfg.SelectCatalogers = Flatten(cfg.SelectCatalogers)
|
||||
cfg.Enrich = Flatten(cfg.Enrich)
|
||||
cfg.Catalogers = flatten(cfg.Catalogers)
|
||||
cfg.DefaultCatalogers = flatten(cfg.DefaultCatalogers)
|
||||
cfg.SelectCatalogers = flatten(cfg.SelectCatalogers)
|
||||
cfg.Enrich = flatten(cfg.Enrich)
|
||||
|
||||
// for backwards compatibility
|
||||
cfg.DefaultCatalogers = append(cfg.DefaultCatalogers, cfg.Catalogers...)
|
||||
@@ -304,7 +257,7 @@ func (cfg *Catalog) PostLoad() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func Flatten(commaSeparatedEntries []string) []string {
|
||||
func flatten(commaSeparatedEntries []string) []string {
|
||||
var out []string
|
||||
for _, v := range commaSeparatedEntries {
|
||||
for _, s := range strings.Split(v, ",") {
|
||||
|
||||
@@ -139,7 +139,7 @@ func Test_enrichmentEnabled(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.directives, func(t *testing.T) {
|
||||
got := enrichmentEnabled(Flatten([]string{test.directives}), test.test)
|
||||
got := enrichmentEnabled(flatten([]string{test.directives}), test.test)
|
||||
assert.Equal(t, test.expected, got)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ package options
|
||||
|
||||
import "github.com/anchore/fangs"
|
||||
|
||||
// Config holds a reference to the specific config file(s) that were used to load application configuration
|
||||
// Config holds a reference to the specific config file that was used to load application configuration
|
||||
type Config struct {
|
||||
ConfigFile string `yaml:"config" json:"config" mapstructure:"config"`
|
||||
}
|
||||
|
||||
func (cfg *Config) DescribeFields(descriptions fangs.FieldDescriptionSet) {
|
||||
descriptions.Add(&cfg.ConfigFile, "the configuration file(s) used to load application configuration")
|
||||
descriptions.Add(&cfg.ConfigFile, "the configuration file that was used to load application configuration")
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
|
||||
)
|
||||
|
||||
type dotnetConfig struct {
|
||||
DepPackagesMustHaveDLL bool `mapstructure:"dep-packages-must-have-dll" json:"dep-packages-must-have-dll" yaml:"dep-packages-must-have-dll"`
|
||||
|
||||
DepPackagesMustClaimDLL bool `mapstructure:"dep-packages-must-claim-dll" json:"dep-packages-must-claim-dll" yaml:"dep-packages-must-claim-dll"`
|
||||
|
||||
PropagateDLLClaimsToParents bool `mapstructure:"propagate-dll-claims-to-parents" json:"propagate-dll-claims-to-parents" yaml:"propagate-dll-claims-to-parents"`
|
||||
|
||||
RelaxDLLClaimsWhenBundlingDetected bool `mapstructure:"relax-dll-claims-when-bundling-detected" json:"relax-dll-claims-when-bundling-detected" yaml:"relax-dll-claims-when-bundling-detected"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*dotnetConfig)(nil)
|
||||
|
||||
func (o *dotnetConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.DepPackagesMustHaveDLL, `only keep dep.json packages which an executable on disk is found. The package is also included if a DLL is found for any child package, even if the package itself does not have a DLL.`)
|
||||
descriptions.Add(&o.DepPackagesMustClaimDLL, `only keep dep.json packages which have a runtime/resource DLL claimed in the deps.json targets section (but not necessarily found on disk). The package is also included if any child package claims a DLL, even if the package itself does not claim a DLL.`)
|
||||
descriptions.Add(&o.PropagateDLLClaimsToParents, `treat DLL claims or on-disk evidence for child packages as DLL claims or on-disk evidence for any parent package`)
|
||||
descriptions.Add(&o.RelaxDLLClaimsWhenBundlingDetected, `show all packages from the deps.json if bundling tooling is present as a dependency (e.g. ILRepack)`)
|
||||
}
|
||||
|
||||
func defaultDotnetConfig() dotnetConfig {
|
||||
def := dotnet.DefaultCatalogerConfig()
|
||||
return dotnetConfig{
|
||||
DepPackagesMustHaveDLL: def.DepPackagesMustHaveDLL,
|
||||
DepPackagesMustClaimDLL: def.DepPackagesMustClaimDLL,
|
||||
PropagateDLLClaimsToParents: def.PropagateDLLClaimsToParents,
|
||||
RelaxDLLClaimsWhenBundlingDetected: def.RelaxDLLClaimsWhenBundlingDetected,
|
||||
}
|
||||
}
|
||||
@@ -43,9 +43,9 @@ over to the final syft 1.0 json output this option can be used to ease the trans
|
||||
|
||||
Note: long term support for this option is not guaranteed (it may change or break at any time)`)
|
||||
|
||||
descriptions.Add(&o.Template.Path, `path to the template file to use when rendering the output with the template output format.
|
||||
descriptions.Add(&o.Template.Path, `path to the template file to use when rendering the output with the template output format.
|
||||
Note that all template paths are based on the current syft-json schema`)
|
||||
descriptions.Add(&o.Template.Legacy, `if true, uses the go structs for the syft-json format for templating.
|
||||
descriptions.Add(&o.Template.Legacy, `if true, uses the go structs for the syft-json format for templating.
|
||||
if false, uses the syft-json output for templating (which follows the syft JSON schema exactly).
|
||||
|
||||
Note: long term support for this option is not guaranteed (it may change or break at any time)`)
|
||||
|
||||
@@ -10,8 +10,6 @@ import (
|
||||
type golangConfig struct {
|
||||
SearchLocalModCacheLicenses *bool `json:"search-local-mod-cache-licenses" yaml:"search-local-mod-cache-licenses" mapstructure:"search-local-mod-cache-licenses"`
|
||||
LocalModCacheDir string `json:"local-mod-cache-dir" yaml:"local-mod-cache-dir" mapstructure:"local-mod-cache-dir"`
|
||||
SearchLocalVendorLicenses *bool `json:"search-local-vendor-licenses" yaml:"search-local-vendor-licenses" mapstructure:"search-local-vendor-licenses"`
|
||||
LocalVendorDir string `json:"local-vendor-dir" yaml:"local-vendor-dir" mapstructure:"local-vendor-dir"`
|
||||
SearchRemoteLicenses *bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"`
|
||||
Proxy string `json:"proxy" yaml:"proxy" mapstructure:"proxy"`
|
||||
NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"`
|
||||
@@ -26,9 +24,6 @@ func (o *golangConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.SearchLocalModCacheLicenses, `search for go package licences in the GOPATH of the system running Syft, note that this is outside the
|
||||
container filesystem and potentially outside the root of a local directory scan`)
|
||||
descriptions.Add(&o.LocalModCacheDir, `specify an explicit go mod cache directory, if unset this defaults to $GOPATH/pkg/mod or $HOME/go/pkg/mod`)
|
||||
descriptions.Add(&o.SearchLocalVendorLicenses, `search for go package licences in the vendor folder on the system running Syft, note that this is outside the
|
||||
container filesystem and potentially outside the root of a local directory scan`)
|
||||
descriptions.Add(&o.LocalVendorDir, `specify an explicit go vendor directory, if unset this defaults to ./vendor`)
|
||||
descriptions.Add(&o.SearchRemoteLicenses, `search for go package licences by retrieving the package from a network proxy`)
|
||||
descriptions.Add(&o.Proxy, `remote proxy to use when retrieving go packages from the network,
|
||||
if unset this defaults to $GOPROXY followed by https://proxy.golang.org`)
|
||||
@@ -54,8 +49,6 @@ func defaultGolangConfig() golangConfig {
|
||||
return golangConfig{
|
||||
SearchLocalModCacheLicenses: nil, // this defaults to false, which is the API default
|
||||
LocalModCacheDir: def.LocalModCacheDir,
|
||||
SearchLocalVendorLicenses: nil, // this defaults to false, which is the API default
|
||||
LocalVendorDir: def.LocalVendorDir,
|
||||
SearchRemoteLicenses: nil, // this defaults to false, which is the API default
|
||||
Proxy: strings.Join(def.Proxies, ","),
|
||||
NoProxy: strings.Join(def.NoProxy, ","),
|
||||
|
||||
@@ -6,24 +6,22 @@ import (
|
||||
)
|
||||
|
||||
type javaConfig struct {
|
||||
UseNetwork *bool `yaml:"use-network" json:"use-network" mapstructure:"use-network"`
|
||||
UseMavenLocalRepository *bool `yaml:"use-maven-local-repository" json:"use-maven-local-repository" mapstructure:"use-maven-local-repository"`
|
||||
MavenLocalRepositoryDir string `yaml:"maven-local-repository-dir" json:"maven-local-repository-dir" mapstructure:"maven-local-repository-dir"`
|
||||
MavenURL string `yaml:"maven-url" json:"maven-url" mapstructure:"maven-url"`
|
||||
MaxParentRecursiveDepth int `yaml:"max-parent-recursive-depth" json:"max-parent-recursive-depth" mapstructure:"max-parent-recursive-depth"`
|
||||
ResolveTransitiveDependencies bool `yaml:"resolve-transitive-dependencies" json:"resolve-transitive-dependencies" mapstructure:"resolve-transitive-dependencies"`
|
||||
UseNetwork *bool `yaml:"use-network" json:"use-network" mapstructure:"use-network"`
|
||||
UseMavenLocalRepository *bool `yaml:"use-maven-local-repository" json:"use-maven-local-repository" mapstructure:"use-maven-local-repository"`
|
||||
MavenLocalRepositoryDir string `yaml:"maven-local-repository-dir" json:"maven-local-repository-dir" mapstructure:"maven-local-repository-dir"`
|
||||
MavenURL string `yaml:"maven-url" json:"maven-url" mapstructure:"maven-url"`
|
||||
MaxParentRecursiveDepth int `yaml:"max-parent-recursive-depth" json:"max-parent-recursive-depth" mapstructure:"max-parent-recursive-depth"`
|
||||
}
|
||||
|
||||
func defaultJavaConfig() javaConfig {
|
||||
def := java.DefaultArchiveCatalogerConfig()
|
||||
|
||||
return javaConfig{
|
||||
UseNetwork: nil, // this defaults to false, which is the API default
|
||||
MaxParentRecursiveDepth: def.MaxParentRecursiveDepth,
|
||||
UseMavenLocalRepository: nil, // this defaults to false, which is the API default
|
||||
MavenLocalRepositoryDir: def.MavenLocalRepositoryDir,
|
||||
MavenURL: def.MavenBaseURL,
|
||||
ResolveTransitiveDependencies: def.ResolveTransitiveDependencies,
|
||||
UseNetwork: nil, // this defaults to false, which is the API default
|
||||
MaxParentRecursiveDepth: def.MaxParentRecursiveDepth,
|
||||
UseMavenLocalRepository: nil, // this defaults to false, which is the API default
|
||||
MavenLocalRepositoryDir: def.MavenLocalRepositoryDir,
|
||||
MavenURL: def.MavenBaseURL,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,5 +43,4 @@ TIP: If you want to download all required pom files to the local repository with
|
||||
build, run 'mvn help:effective-pom' before performing the scan with syft.`)
|
||||
descriptions.Add(&o.MavenLocalRepositoryDir, `override the default location of the local Maven repository.
|
||||
the default is the subdirectory '.m2/repository' in your home directory`)
|
||||
descriptions.Add(&o.ResolveTransitiveDependencies, `resolve transient dependencies such as those defined in a dependency's POM on Maven central`)
|
||||
}
|
||||
|
||||
@@ -3,9 +3,8 @@ package options
|
||||
import "github.com/anchore/clio"
|
||||
|
||||
type javaScriptConfig struct {
|
||||
SearchRemoteLicenses *bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"`
|
||||
NpmBaseURL string `json:"npm-base-url" yaml:"npm-base-url" mapstructure:"npm-base-url"`
|
||||
IncludeDevDependencies *bool `json:"include-dev-dependencies" yaml:"include-dev-dependencies" mapstructure:"include-dev-dependencies"`
|
||||
SearchRemoteLicenses *bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"`
|
||||
NpmBaseURL string `json:"npm-base-url" yaml:"npm-base-url" mapstructure:"npm-base-url"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
@@ -15,5 +14,4 @@ var _ interface {
|
||||
func (o *javaScriptConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.SearchRemoteLicenses, `enables Syft to use the network to fill in more detailed license information`)
|
||||
descriptions.Add(&o.NpmBaseURL, `base NPM url to use`)
|
||||
descriptions.Add(&o.IncludeDevDependencies, `include development-scoped dependencies`)
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
)
|
||||
|
||||
type licenseConfig struct {
|
||||
Content cataloging.LicenseContent `yaml:"content" json:"content" mapstructure:"content"`
|
||||
Coverage float64 `yaml:"coverage" json:"coverage" mapstructure:"coverage"`
|
||||
AvailableLicenseContent []cataloging.LicenseContent `yaml:"-" json:"-" mapstructure:"-"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*licenseConfig)(nil)
|
||||
|
||||
func (o *licenseConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.Content, fmt.Sprintf("include the content of licenses in the SBOM for a given syft scan; valid values are: %s", o.AvailableLicenseContent))
|
||||
|
||||
descriptions.Add(&o.Coverage, `adjust the percent as a fraction of the total text, in normalized words, that
|
||||
matches any valid license for the given inputs, expressed as a percentage across all of the licenses matched.`)
|
||||
}
|
||||
|
||||
func (o *licenseConfig) PostLoad() error {
|
||||
validContent := internal.NewSet(o.AvailableLicenseContent...)
|
||||
if !validContent.Contains(o.Content) {
|
||||
return fmt.Errorf("could not use %q as license content option; valid values are: %v", o.Content, validContent.ToSlice())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func defaultLicenseConfig() licenseConfig {
|
||||
cfg := cataloging.DefaultLicenseConfig()
|
||||
return licenseConfig{
|
||||
Content: cfg.IncludeContent,
|
||||
Coverage: cfg.Coverage,
|
||||
AvailableLicenseContent: []cataloging.LicenseContent{
|
||||
cataloging.LicenseContentIncludeAll,
|
||||
cataloging.LicenseContentIncludeUnknown,
|
||||
cataloging.LicenseContentExcludeAll,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/nix"
|
||||
)
|
||||
|
||||
type nixConfig struct {
|
||||
CaptureOwnedFiles bool `json:"capture-owned-files" yaml:"capture-owned-files" mapstructure:"capture-owned-files"`
|
||||
}
|
||||
|
||||
func defaultNixConfig() nixConfig {
|
||||
def := nix.DefaultConfig()
|
||||
return nixConfig{
|
||||
def.CaptureOwnedFiles,
|
||||
}
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*nixConfig)(nil)
|
||||
|
||||
func (o *nixConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.CaptureOwnedFiles, `enumerate all files owned by packages found within Nix store paths`)
|
||||
}
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/anchore/syft/syft/format/cyclonedxjson"
|
||||
"github.com/anchore/syft/syft/format/cyclonedxxml"
|
||||
"github.com/anchore/syft/syft/format/github"
|
||||
"github.com/anchore/syft/syft/format/purls"
|
||||
"github.com/anchore/syft/syft/format/spdxjson"
|
||||
"github.com/anchore/syft/syft/format/spdxtagvalue"
|
||||
"github.com/anchore/syft/syft/format/syftjson"
|
||||
@@ -90,7 +89,7 @@ func (o Output) SBOMWriter() (sbom.Writer, error) {
|
||||
|
||||
usesTemplateOutput := names.Has(string(template.ID))
|
||||
|
||||
if usesTemplateOutput && o.Template.Path == "" {
|
||||
if usesTemplateOutput && o.Format.Template.Path == "" {
|
||||
return nil, fmt.Errorf(`must specify path to template file when using "template" output format`)
|
||||
}
|
||||
|
||||
@@ -128,7 +127,6 @@ func supportedIDs() []sbom.FormatID {
|
||||
table.ID,
|
||||
text.ID,
|
||||
template.ID,
|
||||
purls.ID,
|
||||
|
||||
// encoders that support multiple versions
|
||||
cyclonedxxml.ID,
|
||||
|
||||
@@ -3,9 +3,10 @@ package options
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/fangs"
|
||||
"github.com/anchore/go-homedir"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
@@ -27,7 +28,7 @@ func (o *OutputFile) AddFlags(flags clio.FlagSet) {
|
||||
|
||||
if pfp, ok := flags.(fangs.PFlagSetProvider); ok {
|
||||
flagSet := pfp.PFlagSet()
|
||||
flagSet.Lookup("file").Deprecated = "use: --output FORMAT=PATH"
|
||||
flagSet.Lookup("file").Deprecated = "use: output"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ var _ interface {
|
||||
} = (*packageConfig)(nil)
|
||||
|
||||
func (o *packageConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.SearchIndexedArchives, `search within archives that do contain a file index to search against (zip)
|
||||
descriptions.Add(&o.SearchUnindexedArchives, `search within archives that do contain a file index to search against (zip)
|
||||
note: for now this only applies to the java package cataloger`)
|
||||
descriptions.Add(&o.SearchUnindexedArchives, `search within archives that do not contain a file index to search against (tar, tar.gz, tar.bz2, etc)
|
||||
descriptions.Add(&o.SearchIndexedArchives, `search within archives that do not contain a file index to search against (tar, tar.gz, tar.bz2, etc)
|
||||
note: enabling this may result in a performance impact since all discovered compressed tars will be decompressed
|
||||
note: for now this only applies to the java package cataloger`)
|
||||
descriptions.Add(&o.ExcludeBinaryOverlapByOwnership, `allows users to exclude synthetic binary packages from the sbom
|
||||
|
||||
@@ -5,19 +5,15 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
|
||||
"github.com/anchore/syft/syft/source/sourceproviders"
|
||||
)
|
||||
|
||||
type sourceConfig struct {
|
||||
Name string `json:"name" yaml:"name" mapstructure:"name"`
|
||||
Version string `json:"version" yaml:"version" mapstructure:"version"`
|
||||
Supplier string `json:"supplier" yaml:"supplier" mapstructure:"supplier"`
|
||||
Source string `json:"source" yaml:"source" mapstructure:"source"`
|
||||
BasePath string `yaml:"base-path" json:"base-path" mapstructure:"base-path"` // specify base path for all file paths
|
||||
File fileSource `json:"file" yaml:"file" mapstructure:"file"`
|
||||
Image imageSource `json:"image" yaml:"image" mapstructure:"image"`
|
||||
@@ -31,8 +27,6 @@ var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*sourceConfig)(nil)
|
||||
|
||||
var _ clio.PostLoader = (*imageSource)(nil)
|
||||
|
||||
func (o *sourceConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.File.Digests, `the file digest algorithms to use on the scanned file (options: "md5", "sha1", "sha224", "sha256", "sha384", "sha512")`)
|
||||
descriptions.Add(&o.Image.DefaultPullSource, `allows users to specify which image source should be used to generate the sbom
|
||||
@@ -41,7 +35,6 @@ valid values are: registry, docker, podman`)
|
||||
|
||||
type imageSource struct {
|
||||
DefaultPullSource string `json:"default-pull-source" yaml:"default-pull-source" mapstructure:"default-pull-source"`
|
||||
MaxLayerSize string `json:"max-layer-size" yaml:"max-layer-size" mapstructure:"max-layer-size"`
|
||||
}
|
||||
|
||||
func defaultSourceConfig() sourceConfig {
|
||||
@@ -63,14 +56,7 @@ func (c *fileSource) PostLoad() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *imageSource) PostLoad() error {
|
||||
if c.MaxLayerSize != "" {
|
||||
perFileReadLimit, err := humanize.ParseBytes(c.MaxLayerSize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stereoscopeFile.SetPerFileReadLimit(int64(perFileReadLimit))
|
||||
}
|
||||
func (c imageSource) PostLoad() error {
|
||||
return checkDefaultSourceValues(c.DefaultPullSource)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
)
|
||||
|
||||
type unknownsConfig struct {
|
||||
RemoveWhenPackagesDefined bool `json:"remove-when-packages-defined" yaml:"remove-when-packages-defined" mapstructure:"remove-when-packages-defined"`
|
||||
ExecutablesWithoutPackages bool `json:"executables-without-packages" yaml:"executables-without-packages" mapstructure:"executables-without-packages"`
|
||||
UnexpandedArchives bool `json:"unexpanded-archives" yaml:"unexpanded-archives" mapstructure:"unexpanded-archives"`
|
||||
}
|
||||
|
||||
var _ interface {
|
||||
clio.FieldDescriber
|
||||
} = (*unknownsConfig)(nil)
|
||||
|
||||
func (o *unknownsConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||
descriptions.Add(&o.RemoveWhenPackagesDefined, `remove unknown errors on files with discovered packages`)
|
||||
descriptions.Add(&o.ExecutablesWithoutPackages, `include executables without any identified packages`)
|
||||
descriptions.Add(&o.UnexpandedArchives, `include archives which were not expanded and searched`)
|
||||
}
|
||||
|
||||
func defaultUnknowns() unknownsConfig {
|
||||
def := cataloging.DefaultUnknownsConfig()
|
||||
return unknownsConfig{
|
||||
RemoveWhenPackagesDefined: def.RemoveWhenPackagesDefined,
|
||||
ExecutablesWithoutPackages: def.IncludeExecutablesWithoutPackages,
|
||||
UnexpandedArchives: def.IncludeUnexpandedArchives,
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/go-homedir"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/format"
|
||||
|
||||
@@ -6,10 +6,10 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/pkg/homedir"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/go-homedir"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
@@ -228,8 +228,6 @@ func Test_newSBOMMultiWriter(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_newSBOMWriterDescription(t *testing.T) {
|
||||
h, err := homedir.Dir()
|
||||
require.NoError(t, err)
|
||||
tests := []struct {
|
||||
name string
|
||||
path string
|
||||
@@ -238,7 +236,7 @@ func Test_newSBOMWriterDescription(t *testing.T) {
|
||||
{
|
||||
name: "expand home dir",
|
||||
path: "~/place.txt",
|
||||
expected: filepath.Join(h, "place.txt"),
|
||||
expected: filepath.Join(homedir.Get(), "place.txt"),
|
||||
},
|
||||
{
|
||||
name: "passthrough other paths",
|
||||
|
||||
@@ -78,27 +78,11 @@ var imageOnlyTestCases = []testCase{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find .NET packages (deps.json + .dlls)",
|
||||
name: "find dot net executable",
|
||||
pkgType: pkg.DotnetPkg,
|
||||
pkgLanguage: pkg.Dotnet,
|
||||
pkgInfo: map[string]string{
|
||||
// executable
|
||||
"DocuSign.eSign": "6.8.0.0",
|
||||
// deps.json
|
||||
"AWSSDK.Core": "3.7.10.6",
|
||||
"Microsoft.Extensions.DependencyInjection": "6.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.Logging": "6.0.0",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "6.0.0",
|
||||
"Microsoft.Extensions.Options": "6.0.0",
|
||||
"Microsoft.Extensions.Primitives": "6.0.0",
|
||||
"Newtonsoft.Json": "13.0.1",
|
||||
"Serilog": "2.10.0",
|
||||
"Serilog.Sinks.Console": "4.0.1",
|
||||
//"System.Diagnostics.DiagnosticSource": "6.0.0", // no dll claims in deps.json targets section
|
||||
//"System.Runtime.CompilerServices.Unsafe": "6.0.0", // no dll claims in deps.json targets section
|
||||
"TestCommon": "1.0.0",
|
||||
"TestLibrary": "1.0.0",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -257,11 +241,10 @@ var dirOnlyTestCases = []testCase{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find dotnet packages (.deps.json)",
|
||||
name: "find dotnet packages",
|
||||
pkgType: pkg.DotnetPkg,
|
||||
pkgLanguage: pkg.Dotnet,
|
||||
pkgInfo: map[string]string{
|
||||
// all from deps.json
|
||||
"AWSSDK.Core": "3.7.10.6",
|
||||
"Microsoft.Extensions.DependencyInjection": "6.0.0",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
||||
@@ -272,17 +255,17 @@ var dirOnlyTestCases = []testCase{
|
||||
"Newtonsoft.Json": "13.0.1",
|
||||
"Serilog": "2.10.0",
|
||||
"Serilog.Sinks.Console": "4.0.1",
|
||||
//"System.Diagnostics.DiagnosticSource": "6.0.0", // no dll claims in deps.json targets section
|
||||
//"System.Runtime.CompilerServices.Unsafe": "6.0.0", // no dll claims in deps.json targets section
|
||||
"TestCommon": "1.0.0",
|
||||
"TestLibrary": "1.0.0",
|
||||
"System.Diagnostics.DiagnosticSource": "6.0.0",
|
||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
|
||||
"TestCommon": "1.0.0",
|
||||
"TestLibrary": "1.0.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find java packages including pom.xml", // directory scans can include packages that have yet to be installed
|
||||
pkgType: pkg.JavaPkg,
|
||||
pkgLanguage: pkg.Java,
|
||||
duplicates: 2, // joda-time and example-java-app-maven are included in both pom.xml AND the .jar collection
|
||||
duplicates: 1, // joda-time is included in both pom.xml AND the .jar collection
|
||||
pkgInfo: map[string]string{
|
||||
"example-java-app-maven": "0.1.0",
|
||||
"joda-time": "2.9.2",
|
||||
@@ -435,14 +418,6 @@ var dirOnlyTestCases = []testCase{
|
||||
"ocaml-base-compiler": "4.14.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find terraform packages",
|
||||
pkgType: pkg.TerraformPkg,
|
||||
pkgLanguage: pkg.Go,
|
||||
pkgInfo: map[string]string{
|
||||
"registry.terraform.io/hashicorp/aws": "5.72.1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var commonTestCases = []testCase{
|
||||
@@ -502,15 +477,8 @@ var commonTestCases = []testCase{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find homebrew",
|
||||
pkgType: pkg.HomebrewPkg,
|
||||
pkgInfo: map[string]string{
|
||||
"afflib": "1.2.3",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "find php pear/pecl package",
|
||||
pkgType: pkg.PhpPearPkg,
|
||||
name: "find php pecl package",
|
||||
pkgType: pkg.PhpPeclPkg,
|
||||
pkgLanguage: pkg.PHP,
|
||||
pkgInfo: map[string]string{
|
||||
"memcached": "3.2.0",
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/anchore/stereoscope/pkg/imagetest"
|
||||
"github.com/anchore/syft/syft"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
@@ -75,8 +74,6 @@ func TestPkgCoverageImage(t *testing.T) {
|
||||
definedPkgs.Remove(string(pkg.ConanPkg))
|
||||
definedPkgs.Remove(string(pkg.HackagePkg))
|
||||
definedPkgs.Remove(string(pkg.BinaryPkg))
|
||||
definedPkgs.Remove(string(pkg.BitnamiPkg))
|
||||
definedPkgs.Remove(string(pkg.GraalVMNativeImagePkg))
|
||||
definedPkgs.Remove(string(pkg.HexPkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
|
||||
@@ -85,9 +82,6 @@ func TestPkgCoverageImage(t *testing.T) {
|
||||
definedPkgs.Remove(string(pkg.OpamPkg))
|
||||
definedPkgs.Remove(string(pkg.GithubActionPkg))
|
||||
definedPkgs.Remove(string(pkg.GithubActionWorkflowPkg))
|
||||
definedPkgs.Remove(string(pkg.TerraformPkg))
|
||||
definedPkgs.Remove(string(pkg.PhpPeclPkg)) // we have coverage for pear instead
|
||||
definedPkgs.Remove(string(pkg.CondaPkg))
|
||||
|
||||
var cases []testCase
|
||||
cases = append(cases, commonTestCases...)
|
||||
@@ -95,7 +89,40 @@ func TestPkgCoverageImage(t *testing.T) {
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
assertPackages(t, sbom, c, observedLanguages, observedPkgs)
|
||||
pkgCount := 0
|
||||
|
||||
for a := range sbom.Artifacts.Packages.Enumerate(c.pkgType) {
|
||||
if a.Language.String() != "" {
|
||||
observedLanguages.Add(a.Language.String())
|
||||
}
|
||||
|
||||
observedPkgs.Add(string(a.Type))
|
||||
expectedVersion, ok := c.pkgInfo[a.Name]
|
||||
if !ok {
|
||||
t.Errorf("unexpected package found: %s", a.Name)
|
||||
}
|
||||
|
||||
if expectedVersion != a.Version {
|
||||
t.Errorf("unexpected package version (pkg=%s): %s, expected: %s", a.Name, a.Version, expectedVersion)
|
||||
}
|
||||
|
||||
if a.Language != c.pkgLanguage {
|
||||
t.Errorf("bad language (pkg=%+v): %+v", a.Name, a.Language)
|
||||
}
|
||||
|
||||
if a.Type != c.pkgType {
|
||||
t.Errorf("bad package type (pkg=%+v): %+v", a.Name, a.Type)
|
||||
}
|
||||
pkgCount++
|
||||
}
|
||||
|
||||
if pkgCount != len(c.pkgInfo)+c.duplicates {
|
||||
t.Logf("Discovered packages of type %+v", c.pkgType)
|
||||
for a := range sbom.Artifacts.Packages.Enumerate(c.pkgType) {
|
||||
t.Log(" ", a)
|
||||
}
|
||||
t.Fatalf("unexpected package count: %d!=%d", pkgCount, len(c.pkgInfo))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -145,7 +172,44 @@ func TestPkgCoverageDirectory(t *testing.T) {
|
||||
|
||||
for _, test := range cases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
assertPackages(t, sbom, test, observedLanguages, observedPkgs)
|
||||
actualPkgCount := 0
|
||||
|
||||
for actualPkg := range sbom.Artifacts.Packages.Enumerate(test.pkgType) {
|
||||
observedLanguages.Add(actualPkg.Language.String())
|
||||
observedPkgs.Add(string(actualPkg.Type))
|
||||
|
||||
expectedVersion, ok := test.pkgInfo[actualPkg.Name]
|
||||
if !ok {
|
||||
t.Errorf("unexpected package found: %s", actualPkg.Name)
|
||||
}
|
||||
|
||||
if expectedVersion != actualPkg.Version {
|
||||
t.Errorf("unexpected package version (pkg=%s): %s", actualPkg.Name, actualPkg.Version)
|
||||
}
|
||||
|
||||
var foundLang bool
|
||||
for _, lang := range strings.Split(test.pkgLanguage.String(), ",") {
|
||||
if actualPkg.Language.String() == lang {
|
||||
foundLang = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundLang {
|
||||
t.Errorf("bad language (pkg=%+v): %+v", actualPkg.Name, actualPkg.Language)
|
||||
}
|
||||
|
||||
if actualPkg.Type != test.pkgType {
|
||||
t.Errorf("bad package type (pkg=%+v): %+v", actualPkg.Name, actualPkg.Type)
|
||||
}
|
||||
actualPkgCount++
|
||||
}
|
||||
|
||||
if actualPkgCount != len(test.pkgInfo)+test.duplicates {
|
||||
for actualPkg := range sbom.Artifacts.Packages.Enumerate(test.pkgType) {
|
||||
t.Log(" ", actualPkg)
|
||||
}
|
||||
t.Fatalf("unexpected package count: %d!=%d", actualPkgCount, len(test.pkgInfo))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -154,14 +218,10 @@ func TestPkgCoverageDirectory(t *testing.T) {
|
||||
definedLanguages.Remove(pkg.R.String())
|
||||
observedPkgs.Remove(string(pkg.UnknownPkg))
|
||||
definedPkgs.Remove(string(pkg.BinaryPkg))
|
||||
definedPkgs.Remove(string(pkg.BitnamiPkg))
|
||||
definedPkgs.Remove(string(pkg.GraalVMNativeImagePkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
|
||||
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
|
||||
definedPkgs.Remove(string(pkg.Rpkg))
|
||||
definedPkgs.Remove(string(pkg.UnknownPkg))
|
||||
definedPkgs.Remove(string(pkg.CondaPkg))
|
||||
definedPkgs.Remove(string(pkg.PhpPeclPkg)) // this is covered as pear packages
|
||||
|
||||
// for directory scans we should not expect to see any of the following package types
|
||||
definedPkgs.Remove(string(pkg.KbPkg))
|
||||
@@ -176,61 +236,6 @@ func TestPkgCoverageDirectory(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func assertPackages(t *testing.T, sbom sbom.SBOM, test testCase, observedLanguages *strset.Set, observedPkgs *strset.Set) {
|
||||
actualPkgCount := 0
|
||||
|
||||
for actualPkg := range sbom.Artifacts.Packages.Enumerate(test.pkgType) {
|
||||
observedLanguages.Add(actualPkg.Language.String())
|
||||
observedPkgs.Add(string(actualPkg.Type))
|
||||
|
||||
expectedVersion, ok := test.pkgInfo[actualPkg.Name]
|
||||
if !ok {
|
||||
t.Errorf("unexpected package found: %s", actualPkg.Name)
|
||||
}
|
||||
|
||||
if expectedVersion != actualPkg.Version {
|
||||
t.Errorf("unexpected package version (pkg=%s): %s", actualPkg.Name, actualPkg.Version)
|
||||
}
|
||||
|
||||
var foundLang bool
|
||||
for _, lang := range strings.Split(test.pkgLanguage.String(), ",") {
|
||||
if actualPkg.Language.String() == lang {
|
||||
foundLang = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundLang {
|
||||
t.Errorf("bad language (pkg=%+v): %+v", actualPkg.Name, actualPkg.Language)
|
||||
}
|
||||
|
||||
if actualPkg.Type != test.pkgType {
|
||||
t.Errorf("bad package type (pkg=%+v): %+v", actualPkg.Name, actualPkg.Type)
|
||||
}
|
||||
actualPkgCount++
|
||||
|
||||
// all packages should have at least one location associated with it, and of those locations at least one should be primary evidence
|
||||
locs := actualPkg.Locations.ToSlice()
|
||||
assert.NotEmpty(t, locs, "package %q has no locations (type=%q)", actualPkg.Name, actualPkg.Type)
|
||||
var primaryEvidenceFound bool
|
||||
for _, l := range locs {
|
||||
if _, exists := l.Annotations[pkg.EvidenceAnnotationKey]; !exists {
|
||||
t.Errorf("missing evidence annotation (pkg=%s type=%s)", actualPkg.Name, actualPkg.Type)
|
||||
}
|
||||
if l.Annotations[pkg.EvidenceAnnotationKey] == pkg.PrimaryEvidenceAnnotation {
|
||||
primaryEvidenceFound = true
|
||||
}
|
||||
}
|
||||
assert.True(t, primaryEvidenceFound, "no primary evidence found for package %q", actualPkg.Name)
|
||||
}
|
||||
|
||||
if actualPkgCount != len(test.pkgInfo)+test.duplicates {
|
||||
for actualPkg := range sbom.Artifacts.Packages.Enumerate(test.pkgType) {
|
||||
t.Log(" ", actualPkg)
|
||||
}
|
||||
t.Fatalf("unexpected package count: %d!=%d", actualPkgCount, len(test.pkgInfo))
|
||||
}
|
||||
}
|
||||
|
||||
func TestPkgCoverageImage_HasEvidence(t *testing.T) {
|
||||
sbom, _ := catalogFixtureImage(t, "image-pkg-coverage", source.SquashedScope)
|
||||
|
||||
|
||||
@@ -78,10 +78,7 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
for _, image := range images {
|
||||
originalSBOM, _ := catalogFixtureImage(t, image, source.SquashedScope)
|
||||
// we need a way to inject supplier into this test
|
||||
// supplier is not available as part of the SBOM Config API since the flag
|
||||
// is used in conjunction with the SourceConfig which is injected into generateSBOM during scan
|
||||
originalSBOM.Source.Supplier = "anchore"
|
||||
|
||||
f := encoders.GetByString(test.name)
|
||||
require.NotNil(t, f)
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/anchore/syft/internal/spdxlicense"
|
||||
)
|
||||
|
||||
func TestSPDXLicenseListIsTheLatest(t *testing.T) {
|
||||
resp, err := http.Get("https://spdx.org/licenses/licenses.json")
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get licenses list: %+v", err)
|
||||
}
|
||||
|
||||
type licenseList struct {
|
||||
Version string `json:"licenseListVersion"`
|
||||
Licenses []struct {
|
||||
ID string `json:"licenseId"`
|
||||
Name string `json:"name"`
|
||||
Text string `json:"licenseText"`
|
||||
Deprecated bool `json:"isDeprecatedLicenseId"`
|
||||
OSIApproved bool `json:"isOsiApproved"`
|
||||
SeeAlso []string `json:"seeAlso"`
|
||||
} `json:"licenses"`
|
||||
}
|
||||
|
||||
var latest licenseList
|
||||
if err = json.NewDecoder(resp.Body).Decode(&latest); err != nil {
|
||||
t.Fatalf("unable to decode license list: %+v", err)
|
||||
}
|
||||
|
||||
assert.Equal(t, latest.Version, spdxlicense.Version)
|
||||
}
|
||||
@@ -25,7 +25,7 @@ func TestNpmPackageLockDirectory(t *testing.T) {
|
||||
}
|
||||
|
||||
// ensure that integration test commonTestCases stay in sync with the available catalogers
|
||||
const expectedPackageCount = 2
|
||||
const expectedPackageCount = 6
|
||||
if foundPackages.Size() != expectedPackageCount {
|
||||
t.Errorf("found the wrong set of npm package-lock.json packages (expected: %d, actual: %d)", expectedPackageCount, foundPackages.Size())
|
||||
}
|
||||
|
||||
@@ -52,18 +52,8 @@ func TestAllPackageCatalogersReachableInTasks(t *testing.T) {
|
||||
|
||||
assert.Equal(t, len(taskTagsByName), constructorCount, "mismatch in number of cataloger constructors and task names")
|
||||
|
||||
exceptions := strset.New(
|
||||
// not reachable since they are deprecated
|
||||
"dotnet-portable-executable-cataloger",
|
||||
"dotnet-deps-cataloger",
|
||||
"nix-store-cataloger",
|
||||
"php-pecl-serialized-cataloger",
|
||||
// not reachable by design
|
||||
"sbom-cataloger",
|
||||
)
|
||||
|
||||
for taskName, tags := range taskTagsByName {
|
||||
if exceptions.Has(taskName) {
|
||||
if taskName == "sbom-cataloger" {
|
||||
continue // this is a special case
|
||||
}
|
||||
if !strset.New(tags...).HasAny(pkgcataloging.ImageTag, pkgcataloging.DirectoryTag) {
|
||||
|
||||
@@ -19,7 +19,7 @@ func TestPackageDeduplication(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
scope: source.AllLayersScope,
|
||||
packageCount: 175, // without deduplication this would be ~600
|
||||
packageCount: 178, // without deduplication this would be ~600
|
||||
instanceCount: map[string]int{
|
||||
"basesystem": 1,
|
||||
"wget": 1,
|
||||
@@ -30,15 +30,15 @@ func TestPackageDeduplication(t *testing.T) {
|
||||
locationCount: map[string]int{
|
||||
"basesystem-11-13.el9": 5, // in all layers
|
||||
"curl-minimal-7.76.1-26.el9_3.2.0.1": 2, // base + wget layer
|
||||
"curl-minimal-7.76.1-31.el9": 3, // curl upgrade layer + all above layers
|
||||
"curl-minimal-7.76.1-29.el9_4.1": 3, // curl upgrade layer + all above layers
|
||||
"wget-1.21.1-8.el9_4": 4, // wget + all above layers
|
||||
"vsftpd-3.0.5-6.el9": 2, // vsftpd + all above layers
|
||||
"httpd-2.4.62-4.el9": 1, // last layer
|
||||
"vsftpd-3.0.5-5.el9": 2, // vsftpd + all above layers
|
||||
"httpd-2.4.57-11.el9_4.1": 1, // last layer
|
||||
},
|
||||
},
|
||||
{
|
||||
scope: source.SquashedScope,
|
||||
packageCount: 169,
|
||||
packageCount: 172,
|
||||
instanceCount: map[string]int{
|
||||
"basesystem": 1,
|
||||
"wget": 1,
|
||||
@@ -47,11 +47,11 @@ func TestPackageDeduplication(t *testing.T) {
|
||||
"httpd": 1, // rpm, binary is now excluded by overlap
|
||||
},
|
||||
locationCount: map[string]int{
|
||||
"basesystem-11-13.el9": 1,
|
||||
"curl-minimal-7.76.1-31.el9": 1, // upgrade
|
||||
"wget-1.21.1-8.el9_4": 1,
|
||||
"vsftpd-3.0.5-6.el9": 1,
|
||||
"httpd-2.4.62-4.el9": 1,
|
||||
"basesystem-11-13.el9": 1,
|
||||
"curl-minimal-7.76.1-29.el9_4.1": 1, // upgrade
|
||||
"wget-1.21.1-8.el9_4": 1,
|
||||
"vsftpd-3.0.5-5.el9": 1,
|
||||
"httpd-2.4.57-11.el9_4.1": 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -3,18 +3,18 @@ package integration
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func TestPhotonPackageRegression(t *testing.T) { // Regression: https://github.com/anchore/syft/pull/1997
|
||||
sbom, _ := catalogFixtureImage(t, "image-photon-all-layers", source.AllLayersScope)
|
||||
var count int
|
||||
for range sbom.Artifacts.Packages.Enumerate(pkg.RpmPkg) {
|
||||
count++
|
||||
var packages []pkg.Package
|
||||
for p := range sbom.Artifacts.Packages.Enumerate() {
|
||||
packages = append(packages, p)
|
||||
}
|
||||
|
||||
assert.Greater(t, count, 0, "expected to find RPM packages in the SBOM (but did not)")
|
||||
if len(packages) < 1 {
|
||||
t.Errorf("failed to find packages for photon distro; wanted > 0 got 0")
|
||||
}
|
||||
}
|
||||
|
||||
-2
@@ -1,2 +0,0 @@
|
||||
desc "Advanced Forensic Format"
|
||||
homepage "https://github.com/sshock/AFFLIBv3"
|
||||
+1
-1
@@ -1 +1 @@
|
||||
a:6:{s:4:"name";s:9:"memcached";s:7:"channel";s:12:"pecl.php.net";s:4:"date";s:10:"2022-01-11";s:4:"time";s:8:"15:23:47";s:7:"version";a:2:{s:7:"release";s:5:"3.2.0";s:3:"api";s:5:"3.2.0";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}}
|
||||
a:5:{s:4:"name";s:9:"memcached";s:4:"date";s:10:"2022-01-11";s:4:"time";s:8:"15:23:47";s:7:"version";a:2:{s:7:"release";s:5:"3.2.0";s:3:"api";s:5:"3.2.0";}s:7:"license";a:2:{s:7:"attribs";a:1:{s:3:"uri";s:26:"http://www.php.net/license";}s:8:"_content";s:11:"PHP License";}}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eux
|
||||
|
||||
docker create --name generate-rpmdb-fixture rockylinux:9 sh -c 'tail -f /dev/null'
|
||||
docker create --name generate-rpmdb-fixture centos:latest sh -c 'tail -f /dev/null'
|
||||
|
||||
function cleanup {
|
||||
docker kill generate-rpmdb-fixture
|
||||
|
||||
Generated
-25
@@ -1,25 +0,0 @@
|
||||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/aws" {
|
||||
version = "5.72.1"
|
||||
constraints = ">= 5.72.0"
|
||||
hashes = [
|
||||
"h1:jhd5O5o0CfZCNEwwN0EiDAzb7ApuFrtxJqa6HXW4EKE=",
|
||||
"zh:0dea6843836e926d33469b48b948744079023816d16a2ff7666bcfb6aa3522d4",
|
||||
"zh:195fa9513f75800a0d62797ebec75ee73e9b8c28d713fe9b63d3b1d1eec129b3",
|
||||
"zh:1ed92f3961715bf0e024bcde3c12dfbdc50b00c1f8a43cc00802cfc45a256208",
|
||||
"zh:2ac687e3a52606466cae4a6813e81d923042488df88d2424e28d3f8530f091bb",
|
||||
"zh:32e7ca75f9314557daada3c44628fe1f3bf964a4f833bfb4b2295d833fe64b6f",
|
||||
"zh:374ee0e6b4327cc6ef666908ce5d6450a3a56e90cd2b785e83c2bcfc100021d2",
|
||||
"zh:5500fd6fdac44f96411fcf9c6d01691159ec35455ed127eb4c3a498e1cc92a64",
|
||||
"zh:723a2dc4b064c12e7ee62ad4fbfd72fa5e025206ea47b735994ef53f3c373152",
|
||||
"zh:89d97b87605f1d734f27e642567cbecf785b521af8ea81dac55c77ccde876221",
|
||||
"zh:951ee1e5731e8d65d521d71b95927e55055b3c4656eef6d46fa580a63328befc",
|
||||
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
|
||||
"zh:9b2b362470b64ec227b2da64762ab8bc4111c6b80365fd9d82fc5e1e33f44038",
|
||||
"zh:aa6e57d0cb974ff0da5dee5d43ad2745cbbc4a2b507d4c799839b9fa96daf688",
|
||||
"zh:ba0d14c4a6b7aa844a830d47c0bf995b632e37f0795394b5b60c638b62b7fc03",
|
||||
"zh:c9764065a9c5d324db0b02bd201b9e3a2118e49c4960884acdeea377173302e9",
|
||||
]
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/anchore/stereoscope/pkg/imagetest"
|
||||
"github.com/anchore/syft/cmd/syft/internal/options"
|
||||
"github.com/anchore/syft/syft"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
@@ -21,7 +20,7 @@ func catalogFixtureImage(t *testing.T, fixtureImageName string, scope source.Sco
|
||||
Name: "syft-tester",
|
||||
Version: "v0.99.0",
|
||||
}).WithCatalogerSelection(
|
||||
cataloging.NewSelectionRequest().
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
WithExpression(catalogerSelection...),
|
||||
)
|
||||
cfg.Search.Scope = scope
|
||||
@@ -56,7 +55,7 @@ func catalogDirectory(t *testing.T, dir string, catalogerSelection ...string) (s
|
||||
Name: "syft-tester",
|
||||
Version: "v0.99.0",
|
||||
}).WithCatalogerSelection(
|
||||
cataloging.NewSelectionRequest().
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
WithExpression(catalogerSelection...),
|
||||
)
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@ const defaultStdoutLogBufferSize = 1024
|
||||
// restore := CaptureStdoutToTraceLog()
|
||||
// // here, stdout will be captured and redirected to the provided writer
|
||||
// restore() // block until the output has all been sent to the writer and restore the original stdout
|
||||
func CaptureStdoutToTraceLog() func() {
|
||||
func CaptureStdoutToTraceLog() (close func()) {
|
||||
return capture(&os.Stdout, newLogWriter(), defaultStdoutLogBufferSize)
|
||||
}
|
||||
|
||||
func capture(target **os.File, writer io.Writer, bufSize int) func() {
|
||||
func capture(target **os.File, writer io.Writer, bufSize int) (close func()) {
|
||||
original := *target
|
||||
|
||||
r, w, _ := os.Pipe()
|
||||
@@ -36,7 +36,11 @@ func capture(target **os.File, writer io.Writer, bufSize int) func() {
|
||||
}()
|
||||
|
||||
buf := make([]byte, bufSize)
|
||||
for original != nil {
|
||||
for {
|
||||
if original == nil {
|
||||
break
|
||||
}
|
||||
|
||||
n, err := r.Read(buf)
|
||||
if n > 0 {
|
||||
_, _ = writer.Write(buf[0:n])
|
||||
|
||||
@@ -78,13 +78,6 @@ func (m *UI) Handle(e partybus.Event) error {
|
||||
}
|
||||
|
||||
func (m *UI) Teardown(force bool) error {
|
||||
defer func() {
|
||||
// allow for traditional logging to resume now that the UI is shutting down
|
||||
if logWrapper, ok := log.Get().(logger.Controller); ok {
|
||||
logWrapper.SetOutput(m.err)
|
||||
}
|
||||
}()
|
||||
|
||||
if !force {
|
||||
m.handler.Wait()
|
||||
m.program.Quit()
|
||||
@@ -150,7 +143,7 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
}
|
||||
|
||||
case partybus.Event:
|
||||
log.WithFields("component", "ui", "event", msg.Type).Trace("event")
|
||||
log.WithFields("component", "ui").Tracef("event: %q", msg.Type)
|
||||
|
||||
switch msg.Type {
|
||||
case event.CLIReport, event.CLINotification, event.CLIAppUpdateAvailable:
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"io"
|
||||
"path"
|
||||
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
@@ -77,6 +76,7 @@ func newAlpineConfiguration(resolver file.Resolver) (*AlpineConfiguration, []fil
|
||||
return &AlpineConfiguration{
|
||||
APKKeys: keys,
|
||||
}, locations, nil
|
||||
|
||||
}
|
||||
|
||||
func getVersion(resolver file.Resolver) (string, []file.Location, error) {
|
||||
@@ -92,7 +92,6 @@ func getVersion(resolver file.Resolver) (string, []file.Location, error) {
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("unable to read alpine version: %w", err)
|
||||
}
|
||||
defer internal.CloseAndLogError(reader, locations[0].RealPath)
|
||||
|
||||
version, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
@@ -112,11 +111,7 @@ func getAPKKeys(resolver file.Resolver) (map[string]string, []file.Location, err
|
||||
}
|
||||
for _, location := range locations {
|
||||
basename := path.Base(location.RealPath)
|
||||
//nolint:gocritic
|
||||
reader, err := resolver.FileContentsByLocation(location)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to resolve file contents by location at %s: %w", location.RealPath, err)
|
||||
}
|
||||
content, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to read apk key content at %s: %w", location.RealPath, err)
|
||||
|
||||
@@ -6,8 +6,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"go.yaml.in/yaml/v3"
|
||||
_ "modernc.org/sqlite" // required for rpmdb and other features
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/anchore/syft/syft"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
@@ -75,7 +74,7 @@ func getSBOM(src source.Source) sbom.SBOM {
|
||||
// only use OS related catalogers that would have been used with the kind of
|
||||
// source type (container image or directory), but also add a specific python cataloger
|
||||
WithCatalogerSelection(
|
||||
cataloging.NewSelectionRequest().
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
WithSubSelections("os").
|
||||
WithAdditions("python-package-cataloger"),
|
||||
).
|
||||
@@ -125,4 +124,5 @@ func showAlpineConfiguration(s sbom.SBOM) {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(string(meta))
|
||||
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
_ "modernc.org/sqlite" // required for rpmdb and other features
|
||||
|
||||
"github.com/anchore/syft/syft"
|
||||
"github.com/anchore/syft/syft/format"
|
||||
"github.com/anchore/syft/syft/format/syftjson"
|
||||
|
||||
@@ -5,10 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
|
||||
_ "modernc.org/sqlite" // required for rpmdb and other features
|
||||
|
||||
"github.com/anchore/syft/syft"
|
||||
"github.com/anchore/syft/syft/cataloging"
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
@@ -32,6 +29,7 @@ func main() {
|
||||
if err := enc.Encode(sbom.Descriptor.Configuration); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func imageReference() string {
|
||||
@@ -57,7 +55,7 @@ func getSBOM(src source.Source, defaultTags ...string) sbom.SBOM {
|
||||
WithCatalogerSelection(
|
||||
// here you can sub-select, add, remove catalogers from the default selection...
|
||||
// or replace the default selection entirely!
|
||||
cataloging.NewSelectionRequest().
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
WithDefaults(defaultTags...),
|
||||
)
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
_ "modernc.org/sqlite" // required for rpmdb and other features
|
||||
|
||||
"github.com/anchore/syft/syft"
|
||||
"github.com/anchore/syft/syft/format/syftjson"
|
||||
)
|
||||
|
||||
@@ -1,86 +1,76 @@
|
||||
module github.com/anchore/syft
|
||||
|
||||
go 1.24.1
|
||||
go 1.22.0
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.5.0
|
||||
github.com/CycloneDX/cyclonedx-go v0.9.2
|
||||
github.com/Masterminds/semver/v3 v3.4.0
|
||||
github.com/CycloneDX/cyclonedx-go v0.9.1
|
||||
github.com/Masterminds/semver v1.5.0
|
||||
github.com/Masterminds/sprig/v3 v3.3.0
|
||||
github.com/OneOfOne/xxhash v1.2.8
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
||||
github.com/acobaugh/osrelease v0.1.0
|
||||
github.com/adrg/xdg v0.5.3
|
||||
github.com/anchore/archiver/v3 v3.5.3-0.20241210171143-5b1d8d1c7c51
|
||||
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9
|
||||
github.com/anchore/clio v0.0.0-20250319180342-2cfe4b0cb716
|
||||
github.com/anchore/fangs v0.0.0-20250319222917-446a1e748ec2
|
||||
github.com/anchore/clio v0.0.0-20240522144804-d81e109008aa
|
||||
github.com/anchore/fangs v0.0.0-20240903175602-e716ef12c23d
|
||||
github.com/anchore/go-collections v0.0.0-20240216171411-9321230ce537
|
||||
github.com/anchore/go-homedir v0.0.0-20250319154043-c29668562e4d
|
||||
github.com/anchore/go-logger v0.0.0-20250318195838-07ae343dd722
|
||||
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a
|
||||
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb
|
||||
github.com/anchore/go-rpmdb v0.0.0-20250516171929-f77691e1faec
|
||||
github.com/anchore/go-sync v0.0.0-20250326131806-4eda43a485b6
|
||||
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04
|
||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20250220190351-d62adb6e1115
|
||||
github.com/anchore/stereoscope v0.1.9-0.20250826202322-ef061ea78385
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20240507183024-848e011fc24f
|
||||
github.com/anchore/stereoscope v0.0.3
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
|
||||
github.com/aquasecurity/go-pep440-version v0.0.1
|
||||
github.com/bitnami/go-version v0.0.0-20250131085805-b1f57a8634ef
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
github.com/bmatcuk/doublestar/v4 v4.9.1
|
||||
github.com/charmbracelet/bubbles v0.21.0
|
||||
github.com/charmbracelet/bubbletea v1.3.6
|
||||
github.com/charmbracelet/lipgloss v1.1.0
|
||||
// we are hinting brotli to latest due to warning when installing archiver v3:
|
||||
// go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption
|
||||
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1
|
||||
github.com/charmbracelet/bubbles v0.20.0
|
||||
github.com/charmbracelet/bubbletea v1.1.1
|
||||
github.com/charmbracelet/lipgloss v0.13.0
|
||||
github.com/dave/jennifer v1.7.1
|
||||
github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da
|
||||
github.com/diskfs/go-diskfs v1.7.0
|
||||
github.com/distribution/reference v0.6.0
|
||||
github.com/docker/docker v27.3.0+incompatible
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/elliotchance/phpserialize v1.4.0
|
||||
github.com/facebookincubator/nvdtools v0.1.5
|
||||
github.com/github/go-spdx/v2 v2.3.3
|
||||
github.com/gkampitakis/go-snaps v0.5.14
|
||||
github.com/go-git/go-billy/v5 v5.6.2
|
||||
github.com/go-git/go-git/v5 v5.16.2
|
||||
github.com/github/go-spdx/v2 v2.3.2
|
||||
github.com/gkampitakis/go-snaps v0.5.7
|
||||
github.com/go-git/go-billy/v5 v5.5.0
|
||||
github.com/go-git/go-git/v5 v5.12.0
|
||||
github.com/go-test/deep v1.1.1
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0
|
||||
github.com/gohugoio/hashstructure v0.5.0
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/google/go-containerregistry v0.20.6
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/google/go-containerregistry v0.20.2
|
||||
github.com/google/licensecheck v0.3.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gookit/color v1.5.4
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2
|
||||
github.com/hashicorp/go-getter v1.7.9
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/hcl/v2 v2.24.0
|
||||
github.com/iancoleman/strcase v0.3.0
|
||||
github.com/invopop/jsonschema v0.7.0
|
||||
github.com/jedib0t/go-pretty/v6 v6.6.8
|
||||
github.com/jedib0t/go-pretty/v6 v6.5.9
|
||||
github.com/jinzhu/copier v0.4.0
|
||||
github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953
|
||||
github.com/magiconair/properties v1.8.10
|
||||
github.com/mholt/archives v0.1.3
|
||||
github.com/knqyf263/go-rpmdb v0.1.1
|
||||
github.com/mholt/archiver/v3 v3.5.1
|
||||
github.com/microsoft/go-rustaudit v0.0.0-20220730194248-4b17361d90a5
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/moby/sys/mountinfo v0.7.2
|
||||
github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1
|
||||
github.com/olekukonko/tablewriter v1.0.9
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/opencontainers/go-digest v1.0.0
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.22
|
||||
github.com/rust-secure-code/go-rustaudit v0.0.0-20250226111315-e20ec32e963c
|
||||
github.com/saferwall/pe v1.5.4
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
|
||||
github.com/sanity-io/litter v1.5.8
|
||||
github.com/sanity-io/litter v1.5.5
|
||||
github.com/sassoftware/go-rpmutils v0.4.0
|
||||
// pinned to pull in 386 arch fix: https://github.com/scylladb/go-set/commit/cc7b2070d91ebf40d233207b633e28f5bd8f03a5
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e
|
||||
github.com/sergi/go-diff v1.4.0
|
||||
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
|
||||
github.com/spdx/tools-golang v0.5.5
|
||||
github.com/spf13/afero v1.14.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/stretchr/testify v1.11.0
|
||||
github.com/spf13/afero v1.11.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/vbatts/go-mtree v0.5.4
|
||||
github.com/vifraa/gopom v1.0.0
|
||||
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651
|
||||
@@ -88,104 +78,87 @@ require (
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1
|
||||
go.uber.org/goleak v1.3.0
|
||||
go.yaml.in/yaml/v3 v3.0.4
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b
|
||||
golang.org/x/mod v0.27.0
|
||||
golang.org/x/net v0.43.0
|
||||
modernc.org/sqlite v1.38.2
|
||||
golang.org/x/mod v0.21.0
|
||||
golang.org/x/net v0.29.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
modernc.org/sqlite v1.33.1
|
||||
)
|
||||
|
||||
require google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.4.0
|
||||
github.com/OneOfOne/xxhash v1.2.8
|
||||
github.com/adrg/xdg v0.5.0
|
||||
github.com/magiconair/properties v1.8.7
|
||||
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.116.0 // indirect
|
||||
cloud.google.com/go/auth v0.9.9 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.7.0 // indirect
|
||||
cloud.google.com/go/iam v1.2.2 // indirect
|
||||
cloud.google.com/go/storage v1.43.0 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect
|
||||
github.com/DataDog/zstd v1.5.5 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/Microsoft/hcsshim v0.11.7 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.2.0 // indirect
|
||||
github.com/STARRY-S/zip v0.2.1 // indirect
|
||||
github.com/agext/levenshtein v1.2.1 // indirect; indirectt
|
||||
github.com/anchore/go-lzo v0.1.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/Microsoft/hcsshim v0.11.4 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 // indirect
|
||||
github.com/andybalholm/brotli v1.1.2-0.20250424173009-453214e765f3 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
github.com/aquasecurity/go-version v0.0.1 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/aquasecurity/go-version v0.0.0-20210121072130-637058cfe492 // indirect
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.122 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/becheran/wildmatch-go v1.0.0 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/bodgit/plumbing v1.3.0 // indirect
|
||||
github.com/bodgit/sevenzip v1.6.0 // indirect
|
||||
github.com/bodgit/windows v1.0.1 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
||||
github.com/charmbracelet/harmonica v0.2.0 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.9.3 // indirect
|
||||
github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect
|
||||
github.com/charmbracelet/x/term v0.2.1 // indirect
|
||||
github.com/cloudflare/circl v1.6.1 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.2.3 // indirect
|
||||
github.com/charmbracelet/x/term v0.2.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.8 // indirect
|
||||
github.com/containerd/cgroups v1.1.0 // indirect
|
||||
github.com/containerd/containerd v1.7.28 // indirect
|
||||
github.com/containerd/containerd/api v1.8.0 // indirect
|
||||
github.com/containerd/continuity v0.4.4 // indirect
|
||||
github.com/containerd/errdefs v1.0.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/containerd/containerd v1.7.11 // indirect
|
||||
github.com/containerd/continuity v0.4.2 // indirect
|
||||
github.com/containerd/fifo v1.1.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/platforms v0.2.1 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
|
||||
github.com/containerd/ttrpc v1.2.7 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.2.0 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||
github.com/containerd/ttrpc v1.2.2 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.1.1 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/docker/cli v28.3.2+incompatible // indirect
|
||||
github.com/docker/cli v27.1.1+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker v28.3.3+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.9.3 // indirect
|
||||
github.com/docker/go-connections v0.6.0 // indirect
|
||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 // indirect
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
||||
github.com/edsrzf/mmap-go v1.1.0 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||
github.com/fatih/color v1.17.0 // indirect
|
||||
github.com/felixge/fgprof v0.9.5 // indirect
|
||||
github.com/felixge/fgprof v0.9.3 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
||||
github.com/gkampitakis/ciinfo v0.3.2 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.4 // indirect
|
||||
github.com/gkampitakis/ciinfo v0.3.0 // indirect
|
||||
github.com/gkampitakis/go-diff v1.3.2 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-restruct/restruct v1.2.0-alpha // indirect
|
||||
github.com/goccy/go-yaml v1.18.0
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e // indirect
|
||||
github.com/google/s2a-go v0.1.8 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/huandu/xstrings v1.5.0 // indirect
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/klauspost/compress v1.17.8 // indirect
|
||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
|
||||
@@ -196,101 +169,87 @@ require (
|
||||
github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/mikelolasagasti/xz v1.0.1 // indirect
|
||||
github.com/minio/minlz v1.0.0 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/locker v1.0.1 // indirect
|
||||
github.com/moby/sys/sequential v0.6.0 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/moby/sys/signal v0.7.0 // indirect
|
||||
github.com/moby/sys/user v0.3.0 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/termenv v0.16.0 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/nwaples/rardecode v1.1.3 // indirect
|
||||
github.com/nwaples/rardecode/v2 v2.1.0 // indirect
|
||||
github.com/olekukonko/errors v1.1.0 // indirect
|
||||
github.com/olekukonko/ll v0.0.9 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/opencontainers/runc v1.1.14 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect
|
||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||
github.com/pborman/indent v1.2.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.19 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/profile v1.7.0 // indirect
|
||||
github.com/pkg/xattr v0.4.9 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.7.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sahilm/fuzzy v0.1.1 // indirect
|
||||
github.com/secDre4mer/pkcs7 v0.0.0-20240322103146-665324a4461d // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
github.com/sorairolake/lzip-go v0.3.5 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/skeema/knownhosts v1.2.2 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/spf13/viper v1.20.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.19.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/sylabs/sif/v2 v2.21.1 // indirect
|
||||
github.com/sylabs/squashfs v1.0.6 // indirect
|
||||
github.com/sylabs/sif/v2 v2.17.1 // indirect
|
||||
github.com/sylabs/squashfs v1.0.0 // indirect
|
||||
github.com/therootcompany/xz v1.0.1 // indirect
|
||||
github.com/tidwall/gjson v1.18.0 // indirect
|
||||
github.com/tidwall/gjson v1.17.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||
github.com/vbatts/tar-split v0.12.1 // indirect
|
||||
github.com/vbatts/tar-split v0.11.3 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/zclconf/go-cty v1.16.3 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.36.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
|
||||
golang.org/x/crypto v0.41.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.12.0 // indirect
|
||||
golang.org/x/tools v0.35.0
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
google.golang.org/api v0.203.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241113202542-65e8d215514f // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect
|
||||
google.golang.org/grpc v1.67.3 // indirect
|
||||
google.golang.org/protobuf v1.36.4 // indirect
|
||||
golang.org/x/crypto v0.27.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/term v0.24.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
|
||||
google.golang.org/grpc v1.62.1 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
modernc.org/libc v1.66.3 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.11.0 // indirect
|
||||
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
|
||||
modernc.org/libc v1.55.3 // indirect
|
||||
modernc.org/mathutil v1.6.0 // indirect
|
||||
modernc.org/memory v1.8.0 // indirect
|
||||
modernc.org/strutil v1.2.0 // indirect
|
||||
modernc.org/token v1.1.0 // indirect
|
||||
)
|
||||
|
||||
retract (
|
||||
v1.25.0 // published with a replace directive (confusing for API users)
|
||||
v0.53.2
|
||||
v0.53.1 // published accidentally with incorrect license in depdencies
|
||||
v0.53.1 // Published accidentally with incorrect license in depdencies
|
||||
)
|
||||
|
||||
replace github.com/mholt/archiver/v3 v3.5.1 => github.com/anchore/archiver/v3 v3.5.2
|
||||
|
||||
+2
-7
@@ -6,8 +6,7 @@ PROJECT_NAME=syft
|
||||
OWNER=anchore
|
||||
REPO="${PROJECT_NAME}"
|
||||
GITHUB_DOWNLOAD_PREFIX=https://github.com/${OWNER}/${REPO}/releases/download
|
||||
INSTALL_SH_BASE_URL=https://get.anchore.io/${PROJECT_NAME}
|
||||
LEGACY_INSTALL_SH_BASE_URL=https://raw.githubusercontent.com/${OWNER}/${PROJECT_NAME}
|
||||
INSTALL_SH_BASE_URL=https://raw.githubusercontent.com/${OWNER}/${PROJECT_NAME}
|
||||
PROGRAM_ARGS=$@
|
||||
|
||||
# signature verification options
|
||||
@@ -837,11 +836,7 @@ EOF
|
||||
if [ "${DOWNLOAD_TAG_INSTALL_SCRIPT}" = "true" ]; then
|
||||
export DOWNLOAD_TAG_INSTALL_SCRIPT=false
|
||||
log_info "fetching release script for tag='${tag}'"
|
||||
if ! install_script=$(http_copy "${INSTALL_SH_BASE_URL}/${tag}/install.sh" ""); then
|
||||
log_warn "failed to fetch from ${INSTALL_SH_BASE_URL}, trying fallback URL"
|
||||
install_script=$(http_copy "${LEGACY_INSTALL_SH_BASE_URL}/${tag}/install.sh" "")
|
||||
fi
|
||||
echo "${install_script}" | sh -s -- ${PROGRAM_ARGS}
|
||||
http_copy "${INSTALL_SH_BASE_URL}/${tag}/install.sh" "" | sh -s -- ${PROGRAM_ARGS}
|
||||
exit $?
|
||||
fi
|
||||
|
||||
|
||||
+2
-32
@@ -36,8 +36,8 @@ func Notify(message string) {
|
||||
})
|
||||
}
|
||||
|
||||
func StartCatalogerTask(info monitor.GenericTask, size int64, initialStage string) *monitor.TaskProgress {
|
||||
t := &monitor.TaskProgress{
|
||||
func StartCatalogerTask(info monitor.GenericTask, size int64, initialStage string) *monitor.CatalogerTaskProgress {
|
||||
t := &monitor.CatalogerTaskProgress{
|
||||
AtomicStage: progress.NewAtomicStage(initialStage),
|
||||
Manual: progress.NewManual(size),
|
||||
}
|
||||
@@ -50,33 +50,3 @@ func StartCatalogerTask(info monitor.GenericTask, size int64, initialStage strin
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func StartPullSourceTask(info monitor.GenericTask, size int64, initialStage string) *monitor.TaskProgress {
|
||||
t := &monitor.TaskProgress{
|
||||
AtomicStage: progress.NewAtomicStage(initialStage),
|
||||
Manual: progress.NewManual(size),
|
||||
}
|
||||
|
||||
Publish(partybus.Event{
|
||||
Type: event.PullSourceStarted,
|
||||
Source: info,
|
||||
Value: progress.StagedProgressable(t),
|
||||
})
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func StartIndexingFiles(path string) *monitor.TaskProgress {
|
||||
t := &monitor.TaskProgress{
|
||||
AtomicStage: progress.NewAtomicStage(""),
|
||||
Manual: progress.NewManual(-1),
|
||||
}
|
||||
|
||||
Publish(partybus.Event{
|
||||
Type: event.FileIndexingStarted,
|
||||
Source: path,
|
||||
Value: progress.StagedProgressable(t),
|
||||
})
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/gohugoio/hashstructure"
|
||||
"github.com/mitchellh/hashstructure/v2"
|
||||
)
|
||||
|
||||
// hashType returns a stable hash based on the structure of the type
|
||||
@@ -12,7 +12,7 @@ func hashType[T any]() string {
|
||||
// get the base type and hash an empty instance
|
||||
var t T
|
||||
empty := emptyValue(reflect.TypeOf(t)).Interface()
|
||||
hash, err := hashstructure.Hash(empty, &hashstructure.HashOptions{
|
||||
hash, err := hashstructure.Hash(empty, hashstructure.FormatV2, &hashstructure.HashOptions{
|
||||
ZeroNil: false,
|
||||
IgnoreZeroValue: false,
|
||||
SlicesAsSets: false,
|
||||
|
||||
Vendored
+2
-2
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/gohugoio/hashstructure"
|
||||
"github.com/mitchellh/hashstructure/v2"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -99,7 +99,7 @@ func Test_hashType(t *testing.T) {
|
||||
|
||||
func Test_hashIgnores(t *testing.T) {
|
||||
hash := func(v any) string {
|
||||
v, err := hashstructure.Hash(v, &hashstructure.HashOptions{})
|
||||
v, err := hashstructure.Hash(v, hashstructure.FormatV2, &hashstructure.HashOptions{})
|
||||
require.NoError(t, err)
|
||||
return fmt.Sprintf("%x", v)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user