mirror of
https://github.com/anchore/syft.git
synced 2026-11-05 17:06:32 +01:00
Compare commits
661
Commits
+24
-8
@@ -2,7 +2,7 @@ tools:
|
|||||||
# we want to use a pinned version of binny to manage the toolchain (so binny manages itself!)
|
# we want to use a pinned version of binny to manage the toolchain (so binny manages itself!)
|
||||||
- name: binny
|
- name: binny
|
||||||
version:
|
version:
|
||||||
want: v0.7.0
|
want: v0.9.0
|
||||||
method: github-release
|
method: github-release
|
||||||
with:
|
with:
|
||||||
repo: anchore/binny
|
repo: anchore/binny
|
||||||
@@ -18,7 +18,7 @@ tools:
|
|||||||
# used to sign mac binaries at release
|
# used to sign mac binaries at release
|
||||||
- name: quill
|
- name: quill
|
||||||
version:
|
version:
|
||||||
want: v0.4.1
|
want: v0.5.1
|
||||||
method: github-release
|
method: github-release
|
||||||
with:
|
with:
|
||||||
repo: anchore/quill
|
repo: anchore/quill
|
||||||
@@ -26,7 +26,7 @@ tools:
|
|||||||
# used for linting
|
# used for linting
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
version:
|
version:
|
||||||
want: v1.59.0
|
want: v2.1.6
|
||||||
method: github-release
|
method: github-release
|
||||||
with:
|
with:
|
||||||
repo: golangci/golangci-lint
|
repo: golangci/golangci-lint
|
||||||
@@ -34,7 +34,7 @@ tools:
|
|||||||
# used for showing the changelog at release
|
# used for showing the changelog at release
|
||||||
- name: glow
|
- name: glow
|
||||||
version:
|
version:
|
||||||
want: v1.5.1
|
want: v2.1.0
|
||||||
method: github-release
|
method: github-release
|
||||||
with:
|
with:
|
||||||
repo: charmbracelet/glow
|
repo: charmbracelet/glow
|
||||||
@@ -42,7 +42,7 @@ tools:
|
|||||||
# used for signing the checksums file at release
|
# used for signing the checksums file at release
|
||||||
- name: cosign
|
- name: cosign
|
||||||
version:
|
version:
|
||||||
want: v2.2.4
|
want: v2.5.0
|
||||||
method: github-release
|
method: github-release
|
||||||
with:
|
with:
|
||||||
repo: sigstore/cosign
|
repo: sigstore/cosign
|
||||||
@@ -58,7 +58,7 @@ tools:
|
|||||||
# used to release all artifacts
|
# used to release all artifacts
|
||||||
- name: goreleaser
|
- name: goreleaser
|
||||||
version:
|
version:
|
||||||
want: v1.26.2
|
want: v2.9.0
|
||||||
method: github-release
|
method: github-release
|
||||||
with:
|
with:
|
||||||
repo: goreleaser/goreleaser
|
repo: goreleaser/goreleaser
|
||||||
@@ -103,7 +103,7 @@ tools:
|
|||||||
# used for running all local and CI tasks
|
# used for running all local and CI tasks
|
||||||
- name: task
|
- name: task
|
||||||
version:
|
version:
|
||||||
want: v3.37.2
|
want: v3.43.3
|
||||||
method: github-release
|
method: github-release
|
||||||
with:
|
with:
|
||||||
repo: go-task/task
|
repo: go-task/task
|
||||||
@@ -111,7 +111,23 @@ tools:
|
|||||||
# used for triggering a release
|
# used for triggering a release
|
||||||
- name: gh
|
- name: gh
|
||||||
version:
|
version:
|
||||||
want: v2.49.2
|
want: v2.72.0
|
||||||
method: github-release
|
method: github-release
|
||||||
with:
|
with:
|
||||||
repo: cli/cli
|
repo: cli/cli
|
||||||
|
|
||||||
|
# used to upload test fixture cache
|
||||||
|
- name: oras
|
||||||
|
version:
|
||||||
|
want: v1.2.3
|
||||||
|
method: github-release
|
||||||
|
with:
|
||||||
|
repo: oras-project/oras
|
||||||
|
|
||||||
|
# used to upload test fixture cache
|
||||||
|
- name: yq
|
||||||
|
version:
|
||||||
|
want: v4.45.4
|
||||||
|
method: github-release
|
||||||
|
with:
|
||||||
|
repo: mikefarah/yq
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ permit:
|
|||||||
- MPL.*
|
- MPL.*
|
||||||
- ISC
|
- ISC
|
||||||
- WTFPL
|
- WTFPL
|
||||||
|
- Unlicense
|
||||||
|
|
||||||
ignore-packages:
|
ignore-packages:
|
||||||
# packageurl-go is released under the MIT license located in the root of the repo at /mit.LICENSE
|
# packageurl-go is released under the MIT license located in the root of the repo at /mit.LICENSE
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
contact_links:
|
contact_links:
|
||||||
|
|
||||||
- name: Join the Slack community 💬
|
- name: Join our Discourse community 💬
|
||||||
# link to our community Slack registration page
|
# link to our community Discourse site
|
||||||
url: https://anchore.com/slack
|
url: https://anchore.com/discourse
|
||||||
about: 'Come chat with us! Ask for help, join our software development efforts, or just give us feedback!'
|
about: 'Come chat with us! Ask for help, join our software development efforts, or just give us feedback!'
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ inputs:
|
|||||||
go-version:
|
go-version:
|
||||||
description: "Go version to install"
|
description: "Go version to install"
|
||||||
required: true
|
required: true
|
||||||
default: "1.21.x"
|
default: ">= 1.24"
|
||||||
go-dependencies:
|
go-dependencies:
|
||||||
description: "Download go dependencies"
|
description: "Download go dependencies"
|
||||||
required: true
|
required: true
|
||||||
@@ -13,34 +13,38 @@ inputs:
|
|||||||
cache-key-prefix:
|
cache-key-prefix:
|
||||||
description: "Prefix all cache keys with this value"
|
description: "Prefix all cache keys with this value"
|
||||||
required: true
|
required: true
|
||||||
default: "1ac8281053"
|
default: "181053ac82"
|
||||||
compute-fingerprints:
|
download-test-fixture-cache:
|
||||||
description: "Compute test fixture fingerprints"
|
description: "Download test fixture cache from OCI and github actions"
|
||||||
required: true
|
required: true
|
||||||
|
default: "false"
|
||||||
|
tools:
|
||||||
|
description: "whether to install tools"
|
||||||
default: "true"
|
default: "true"
|
||||||
bootstrap-apt-packages:
|
bootstrap-apt-packages:
|
||||||
description: "Space delimited list of tools to install via apt"
|
description: "Space delimited list of tools to install via apt"
|
||||||
default: "libxml2-utils"
|
default: "libxml2-utils"
|
||||||
|
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
# note: go mod and build is automatically cached on default with v4+
|
# note: go mod and build is automatically cached on default with v4+
|
||||||
- uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 #v5.0.1
|
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
|
||||||
if: inputs.go-version != ''
|
if: inputs.go-version != ''
|
||||||
with:
|
with:
|
||||||
go-version: ${{ inputs.go-version }}
|
go-version: ${{ inputs.go-version }}
|
||||||
|
|
||||||
- name: Restore tool cache
|
- name: Restore tool cache
|
||||||
|
if: inputs.tools == 'true'
|
||||||
id: tool-cache
|
id: tool-cache
|
||||||
uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 #v3.3.2
|
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
with:
|
with:
|
||||||
path: ${{ github.workspace }}/.tool
|
path: ${{ github.workspace }}/.tool
|
||||||
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('.binny.yaml') }}
|
key: ${{ inputs.cache-key-prefix }}-${{ runner.os }}-tool-${{ hashFiles('.binny.yaml') }}
|
||||||
|
|
||||||
- name: Install project tools
|
- name: Install project tools
|
||||||
shell: bash
|
shell: bash
|
||||||
|
if: inputs.tools == 'true'
|
||||||
run: make tools
|
run: make tools
|
||||||
|
|
||||||
- name: Install go dependencies
|
- name: Install go dependencies
|
||||||
@@ -54,8 +58,14 @@ runs:
|
|||||||
run: |
|
run: |
|
||||||
DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y ${{ inputs.bootstrap-apt-packages }}
|
DEBIAN_FRONTEND=noninteractive sudo apt update && sudo -E apt install -y ${{ inputs.bootstrap-apt-packages }}
|
||||||
|
|
||||||
- name: Create all cache fingerprints
|
- name: Restore ORAS cache from github actions
|
||||||
if: inputs.compute-fingerprints == 'true'
|
if: inputs.download-test-fixture-cache == 'true'
|
||||||
shell: bash
|
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||||
run: make fingerprints
|
with:
|
||||||
|
path: ${{ github.workspace }}/.tmp/oras-cache
|
||||||
|
key: ${{ inputs.cache-key-prefix }}-oras-cache
|
||||||
|
|
||||||
|
- name: Download test fixture cache
|
||||||
|
if: inputs.download-test-fixture-cache == 'true'
|
||||||
|
shell: bash
|
||||||
|
run: make download-test-fixture-cache
|
||||||
|
|||||||
@@ -17,3 +17,11 @@ updates:
|
|||||||
open-pull-requests-limit: 10
|
open-pull-requests-limit: 10
|
||||||
labels:
|
labels:
|
||||||
- "dependencies"
|
- "dependencies"
|
||||||
|
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/.github/actions/bootstrap"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
labels:
|
||||||
|
- "dependencies"
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# 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
|
||||||
Executable
+137
@@ -0,0 +1,137 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import glob
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
|
||||||
|
IGNORED_PREFIXES = []
|
||||||
|
|
||||||
|
|
||||||
|
def find_fingerprints_and_check_dirs(base_dir):
|
||||||
|
all_fingerprints = set(glob.glob(os.path.join(base_dir, '**', 'test*', '**', '*.fingerprint'), recursive=True))
|
||||||
|
|
||||||
|
all_fingerprints = {os.path.relpath(fp) for fp in all_fingerprints
|
||||||
|
if not any(fp.startswith(prefix) for prefix in IGNORED_PREFIXES)}
|
||||||
|
|
||||||
|
if not all_fingerprints:
|
||||||
|
show("No .fingerprint files or cache directories found.")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
missing_content = []
|
||||||
|
valid_paths = set()
|
||||||
|
fingerprint_contents = []
|
||||||
|
|
||||||
|
for fingerprint in all_fingerprints:
|
||||||
|
path = fingerprint.replace('.fingerprint', '')
|
||||||
|
|
||||||
|
if not os.path.exists(path):
|
||||||
|
missing_content.append(path)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
valid_paths.add(path)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if os.listdir(path):
|
||||||
|
valid_paths.add(path)
|
||||||
|
else:
|
||||||
|
missing_content.append(path)
|
||||||
|
|
||||||
|
with open(fingerprint, 'r') as f:
|
||||||
|
content = f.read().strip()
|
||||||
|
fingerprint_contents.append((fingerprint, content))
|
||||||
|
|
||||||
|
return sorted(valid_paths), missing_content, fingerprint_contents
|
||||||
|
|
||||||
|
|
||||||
|
def parse_fingerprint_contents(fingerprint_content):
|
||||||
|
input_map = {}
|
||||||
|
for line in fingerprint_content.splitlines():
|
||||||
|
digest, path = line.split()
|
||||||
|
input_map[path] = digest
|
||||||
|
return input_map
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_sha256(fingerprint_contents):
|
||||||
|
sorted_fingerprint_contents = sorted(fingerprint_contents, key=lambda x: x[0])
|
||||||
|
|
||||||
|
concatenated_contents = ''.join(content for _, content in sorted_fingerprint_contents)
|
||||||
|
|
||||||
|
sha256_hash = hashlib.sha256(concatenated_contents.encode()).hexdigest()
|
||||||
|
|
||||||
|
return sha256_hash
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_file_sha256(file_path):
|
||||||
|
sha256_hash = hashlib.sha256()
|
||||||
|
with open(file_path, 'rb') as f:
|
||||||
|
for byte_block in iter(lambda: f.read(4096), b""):
|
||||||
|
sha256_hash.update(byte_block)
|
||||||
|
return sha256_hash.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def show(*s: str):
|
||||||
|
print(*s, file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
def main(file_path: str | None):
|
||||||
|
base_dir = '.'
|
||||||
|
valid_paths, missing_content, fingerprint_contents = find_fingerprints_and_check_dirs(base_dir)
|
||||||
|
|
||||||
|
if missing_content:
|
||||||
|
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)
|
||||||
|
|
||||||
|
sha256_hash = calculate_sha256(fingerprint_contents)
|
||||||
|
|
||||||
|
paths_with_digests = []
|
||||||
|
for path in sorted(valid_paths):
|
||||||
|
fingerprint_file = f"{path}.fingerprint"
|
||||||
|
try:
|
||||||
|
if os.path.exists(fingerprint_file):
|
||||||
|
file_digest = calculate_file_sha256(fingerprint_file)
|
||||||
|
|
||||||
|
# Parse the fingerprint file to get the digest/path tuples
|
||||||
|
with open(fingerprint_file, 'r') as f:
|
||||||
|
fingerprint_content = f.read().strip()
|
||||||
|
input_map = parse_fingerprint_contents(fingerprint_content)
|
||||||
|
|
||||||
|
paths_with_digests.append({
|
||||||
|
"path": path,
|
||||||
|
"digest": file_digest,
|
||||||
|
"input": input_map
|
||||||
|
})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
show(f"Error processing {fingerprint_file}: {e}")
|
||||||
|
raise e
|
||||||
|
|
||||||
|
|
||||||
|
output = {
|
||||||
|
"digest": sha256_hash,
|
||||||
|
"paths": paths_with_digests
|
||||||
|
}
|
||||||
|
|
||||||
|
content = json.dumps(output, indent=2, sort_keys=True)
|
||||||
|
|
||||||
|
if file_path:
|
||||||
|
with open(file_path, 'w') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
print(content)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
file_path = None
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
file_path = sys.argv[1]
|
||||||
|
main(file_path)
|
||||||
+70
@@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
BOLD = '\033[1m'
|
||||||
|
YELLOW = '\033[0;33m'
|
||||||
|
RESET = '\033[0m'
|
||||||
|
|
||||||
|
|
||||||
|
def print_message(message):
|
||||||
|
print(f"{YELLOW}{message}{RESET}")
|
||||||
|
|
||||||
|
|
||||||
|
def sha256sum(filepath):
|
||||||
|
h = hashlib.sha256()
|
||||||
|
with open(filepath, 'rb') as f:
|
||||||
|
for chunk in iter(lambda: f.read(4096), b""):
|
||||||
|
h.update(chunk)
|
||||||
|
return h.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def is_git_tracked_or_untracked(directory):
|
||||||
|
"""Returns a sorted list of files in the directory that are tracked or not ignored by Git."""
|
||||||
|
result = subprocess.run(
|
||||||
|
["git", "ls-files", "--cached", "--others", "--exclude-standard"],
|
||||||
|
cwd=directory,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
text=True
|
||||||
|
)
|
||||||
|
return sorted(result.stdout.strip().splitlines())
|
||||||
|
|
||||||
|
|
||||||
|
def find_test_fixture_dirs_with_images(base_dir):
|
||||||
|
"""Find directories that contain 'test-fixtures' and at least one 'image-*' directory."""
|
||||||
|
for root, dirs, files in os.walk(base_dir):
|
||||||
|
if 'test-fixtures' in root:
|
||||||
|
image_dirs = [d for d in dirs if d.startswith('image-')]
|
||||||
|
if image_dirs:
|
||||||
|
yield os.path.realpath(root)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_fingerprints():
|
||||||
|
print_message("creating fingerprint files for docker fixtures...")
|
||||||
|
|
||||||
|
for test_fixture_dir in find_test_fixture_dirs_with_images('.'):
|
||||||
|
cache_fingerprint_path = os.path.join(test_fixture_dir, 'cache.fingerprint')
|
||||||
|
|
||||||
|
with open(cache_fingerprint_path, 'w') as fingerprint_file:
|
||||||
|
for image_dir in find_image_dirs(test_fixture_dir):
|
||||||
|
for file in is_git_tracked_or_untracked(image_dir):
|
||||||
|
file_path = os.path.join(image_dir, file)
|
||||||
|
checksum = sha256sum(file_path)
|
||||||
|
path_from_fixture_dir = os.path.relpath(file_path, test_fixture_dir)
|
||||||
|
fingerprint_file.write(f"{checksum} {path_from_fixture_dir}\n")
|
||||||
|
|
||||||
|
|
||||||
|
def find_image_dirs(test_fixture_dir):
|
||||||
|
"""Find all 'image-*' directories inside a given test-fixture directory."""
|
||||||
|
result = []
|
||||||
|
for root, dirs, files in os.walk(test_fixture_dir):
|
||||||
|
for dir_name in dirs:
|
||||||
|
if dir_name.startswith('image-'):
|
||||||
|
result.append(os.path.join(root, dir_name))
|
||||||
|
return sorted(result)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
generate_fingerprints()
|
||||||
Regular → Executable
+2
@@ -1,3 +1,5 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|||||||
Regular → Executable
+2
@@ -1,3 +1,5 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|||||||
@@ -4,12 +4,19 @@ set -eu
|
|||||||
bold=$(tput bold)
|
bold=$(tput bold)
|
||||||
normal=$(tput sgr0)
|
normal=$(tput sgr0)
|
||||||
|
|
||||||
if ! [ -x "$(command -v gh)" ]; then
|
GH_CLI=.tool/gh
|
||||||
echo "The GitHub CLI could not be found. To continue follow the instructions at https://github.com/cli/cli#installation"
|
|
||||||
|
if ! [ -x "$(command -v $GH_CLI)" ]; then
|
||||||
|
echo "The GitHub CLI could not be found. run: make bootstrap"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
gh auth status
|
$GH_CLI auth status
|
||||||
|
|
||||||
|
# set the default repo in cases where multiple remotes are defined
|
||||||
|
$GH_CLI repo set-default anchore/syft
|
||||||
|
|
||||||
|
export GITHUB_TOKEN="${GITHUB_TOKEN-"$($GH_CLI auth token)"}"
|
||||||
|
|
||||||
# we need all of the git state to determine the next version. Since tagging is done by
|
# we need all of the git state to determine the next version. Since tagging is done by
|
||||||
# the release pipeline it is possible to not have all of the tags from previous releases.
|
# the release pipeline it is possible to not have all of the tags from previous releases.
|
||||||
@@ -37,7 +44,7 @@ done
|
|||||||
|
|
||||||
echo "${bold}Kicking off release for ${NEXT_VERSION}${normal}..."
|
echo "${bold}Kicking off release for ${NEXT_VERSION}${normal}..."
|
||||||
echo
|
echo
|
||||||
gh workflow run release.yaml -f version=${NEXT_VERSION}
|
$GH_CLI workflow run release.yaml -f version=${NEXT_VERSION}
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "${bold}Waiting for release to start...${normal}"
|
echo "${bold}Waiting for release to start...${normal}"
|
||||||
@@ -45,6 +52,6 @@ sleep 10
|
|||||||
|
|
||||||
set +e
|
set +e
|
||||||
|
|
||||||
echo "${bold}Head to the release workflow to monitor the release:${normal} $(gh run list --workflow=release.yaml --limit=1 --json url --jq '.[].url')"
|
echo "${bold}Head to the release workflow to monitor the release:${normal} $($GH_CLI run list --workflow=release.yaml --limit=1 --json url --jq '.[].url')"
|
||||||
id=$(gh run list --workflow=release.yaml --limit=1 --json databaseId --jq '.[].databaseId')
|
id=$($GH_CLI run list --workflow=release.yaml --limit=1 --json databaseId --jq '.[].databaseId')
|
||||||
gh run watch $id --exit-status || (echo ; echo "${bold}Logs of failed step:${normal}" && GH_PAGER="" gh run view $id --log-failed)
|
$GH_CLI run watch $id --exit-status || (echo ; echo "${bold}Logs of failed step:${normal}" && GH_PAGER="" $GH_CLI run view $id --log-failed)
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
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@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
|
||||||
|
|
||||||
- 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@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
|
|
||||||
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:
|
analyze:
|
||||||
name: Analyze
|
name: Analyze
|
||||||
runs-on: ubuntu-22.04-4core-16gb
|
runs-on: ubuntu-22.04-4core-16gb
|
||||||
|
if: github.repository == 'anchore/syft' # only run for main repo
|
||||||
permissions:
|
permissions:
|
||||||
security-events: write
|
security-events: write
|
||||||
|
|
||||||
@@ -36,16 +36,16 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
- name: Install Go
|
- name: Install Go
|
||||||
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 #v5.0.1
|
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 #v5.5.0
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@9fdb3e49720b44c48891d036bb502feb25684276 #v3.25.6
|
uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f #v3.28.18
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@@ -56,7 +56,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# 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)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@9fdb3e49720b44c48891d036bb502feb25684276 #v3.25.6
|
uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f #v3.28.18
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
@@ -70,4 +70,4 @@ jobs:
|
|||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@9fdb3e49720b44c48891d036bb502feb25684276 #v3.25.6
|
uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f #v3.28.18
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
- run: python .github/scripts/labeler.py
|
- run: python .github/scripts/labeler.py
|
||||||
env:
|
env:
|
||||||
@@ -40,7 +40,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Delete existing comment
|
- name: Delete existing comment
|
||||||
if: ${{ hashFiles( env.CI_COMMENT_FILE ) == '' }}
|
if: ${{ hashFiles( env.CI_COMMENT_FILE ) == '' }}
|
||||||
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0
|
uses: marocchino/sticky-pull-request-comment@67d0dec7b07ed060a405f9b2a64b8ab319fdd7db #v2.9.2
|
||||||
with:
|
with:
|
||||||
header: ${{ env.COMMENT_HEADER }}
|
header: ${{ env.COMMENT_HEADER }}
|
||||||
hide: true
|
hide: true
|
||||||
@@ -48,7 +48,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Add comment
|
- name: Add comment
|
||||||
if: ${{ hashFiles( env.CI_COMMENT_FILE ) != '' }}
|
if: ${{ hashFiles( env.CI_COMMENT_FILE ) != '' }}
|
||||||
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0
|
uses: marocchino/sticky-pull-request-comment@67d0dec7b07ed060a405f9b2a64b8ab319fdd7db #v2.9.2
|
||||||
with:
|
with:
|
||||||
header: ${{ env.COMMENT_HEADER }}
|
header: ${{ env.COMMENT_HEADER }}
|
||||||
path: ${{ env.CI_COMMENT_FILE }}
|
path: ${{ env.CI_COMMENT_FILE }}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
name: "Release"
|
name: "Release: version file"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
|
||||||
@@ -18,9 +18,9 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
release:
|
release:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
- name: Update version file
|
- name: Update version file
|
||||||
run: make ci-release-version-file
|
run: make ci-release-version-file
|
||||||
|
|||||||
@@ -13,9 +13,17 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
quality-gate:
|
quality-gate:
|
||||||
environment: release
|
environment: release
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
|
- name: Check if running on main
|
||||||
|
if: github.ref != 'refs/heads/main'
|
||||||
|
# we are using the following flag when running `cosign blob-verify` for checksum signature verification:
|
||||||
|
# --certificate-identity-regexp "https://github.com/anchore/.github/workflows/release.yaml@refs/heads/main"
|
||||||
|
# if we are not on the main branch, the signature will not be verifiable since the suffix requires the main branch
|
||||||
|
# at the time of when the OIDC token was issued on the Github Actions runner.
|
||||||
|
run: echo "This can only be run on the main branch otherwise releases produced will not be verifiable with cosign" && exit 1
|
||||||
|
|
||||||
- name: Check if tag already exists
|
- name: Check if tag already exists
|
||||||
# note: this will fail if the tag already exists
|
# note: this will fail if the tag already exists
|
||||||
@@ -90,14 +98,14 @@ jobs:
|
|||||||
|
|
||||||
release:
|
release:
|
||||||
needs: [quality-gate]
|
needs: [quality-gate]
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
packages: write
|
packages: write
|
||||||
# required for goreleaser signs section with cosign
|
# required for goreleaser signs section with cosign
|
||||||
id-token: write
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
@@ -105,13 +113,13 @@ jobs:
|
|||||||
uses: ./.github/actions/bootstrap
|
uses: ./.github/actions/bootstrap
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 #v3.2.0
|
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 #v3.4.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.ANCHOREOSSWRITE_DH_USERNAME }}
|
username: ${{ secrets.ANCHOREOSSWRITE_DH_USERNAME }}
|
||||||
password: ${{ secrets.ANCHOREOSSWRITE_DH_PAT }}
|
password: ${{ secrets.ANCHOREOSSWRITE_DH_PAT }}
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 #v3.2.0
|
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 #v3.4.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
@@ -140,12 +148,13 @@ jobs:
|
|||||||
# for updating brew formula in anchore/homebrew-syft
|
# for updating brew formula in anchore/homebrew-syft
|
||||||
GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }}
|
GITHUB_BREW_TOKEN: ${{ secrets.ANCHOREOPS_GITHUB_OSS_WRITE_TOKEN }}
|
||||||
|
|
||||||
- uses: anchore/sbom-action@e8d2a6937ecead383dfe75190d104edd1f9c5751 #v0.16.0
|
- uses: anchore/sbom-action@e11c554f704a0b820cbf8c51673f6945e0731532 #v0.20.0
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
|
file: go.mod
|
||||||
artifact-name: sbom.spdx.json
|
artifact-name: sbom.spdx.json
|
||||||
|
|
||||||
- uses: 8398a7/action-slack@28ba43ae48961b90635b50953d216767a6bea486 #v3.16.2
|
- uses: 8398a7/action-slack@1750b5085f3ec60384090fb7c52965ef822e869e #v3.18.0
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
status: ${{ job.status }}
|
status: ${{ job.status }}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
name: "Manage Awaiting Response Label"
|
||||||
|
|
||||||
|
on:
|
||||||
|
issue_comment:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run:
|
||||||
|
uses: "anchore/workflows/.github/workflows/remove-awaiting-response-label.yaml@main"
|
||||||
|
secrets:
|
||||||
|
token: ${{ secrets.OSS_PROJECT_GH_TOKEN }}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
name: "Test fixture cache: publish"
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
# run nightly at 4AM UTC
|
||||||
|
- cron: "0 4 * * *"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
Publish:
|
||||||
|
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@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
|
- name: Bootstrap environment
|
||||||
|
uses: ./.github/actions/bootstrap
|
||||||
|
with:
|
||||||
|
# we want to rebuild the cache with no previous state
|
||||||
|
download-test-fixture-cache: false
|
||||||
|
|
||||||
|
- name: Run all tests
|
||||||
|
run: make test
|
||||||
|
env:
|
||||||
|
# we want to rebuild the cache with no previous state
|
||||||
|
DOWNLOAD_TEST_FIXTURE_CACHE: "false"
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry (ORAS)
|
||||||
|
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
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
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@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
|
- 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,13 +13,12 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'anchore/syft' # only run for main repo
|
if: github.repository == 'anchore/syft' # only run for main repo
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
- name: Bootstrap environment
|
- name: Bootstrap environment
|
||||||
uses: ./.github/actions/bootstrap
|
uses: ./.github/actions/bootstrap
|
||||||
with:
|
with:
|
||||||
bootstrap-apt-packages: ""
|
bootstrap-apt-packages: ""
|
||||||
compute-fingerprints: "false"
|
|
||||||
go-dependencies: false
|
go-dependencies: false
|
||||||
|
|
||||||
- name: "Update tool versions"
|
- name: "Update tool versions"
|
||||||
@@ -50,7 +49,7 @@ jobs:
|
|||||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
- uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e #v6.0.5
|
- uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e #v7.0.8
|
||||||
with:
|
with:
|
||||||
signoff: true
|
signoff: true
|
||||||
delete-branch: true
|
delete-branch: true
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'anchore/syft' # only run for main repo
|
if: github.repository == 'anchore/syft' # only run for main repo
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
- name: Bootstrap environment
|
- name: Bootstrap environment
|
||||||
uses: ./.github/actions/bootstrap
|
uses: ./.github/actions/bootstrap
|
||||||
@@ -33,7 +33,7 @@ jobs:
|
|||||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
- uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e #v6.0.5
|
- uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e #v7.0.8
|
||||||
with:
|
with:
|
||||||
signoff: true
|
signoff: true
|
||||||
delete-branch: true
|
delete-branch: true
|
||||||
@@ -45,7 +45,7 @@ jobs:
|
|||||||
Update CPE dictionary index based on the latest available CPE dictionary
|
Update CPE dictionary index based on the latest available CPE dictionary
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
- uses: 8398a7/action-slack@28ba43ae48961b90635b50953d216767a6bea486 #v3.16.2
|
- uses: 8398a7/action-slack@1750b5085f3ec60384090fb7c52965ef822e869e #v3.18.0
|
||||||
with:
|
with:
|
||||||
status: ${{ job.status }}
|
status: ${{ job.status }}
|
||||||
fields: workflow,eventName,job
|
fields: workflow,eventName,job
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
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@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
|
||||||
|
|
||||||
- uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 #v5.0.1
|
|
||||||
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@6d6857d36972b65feb161a90e484f2984215f83e #v6.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 }}
|
|
||||||
@@ -15,9 +15,9 @@ jobs:
|
|||||||
Static-Analysis:
|
Static-Analysis:
|
||||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||||
name: "Static analysis"
|
name: "Static analysis"
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
- name: Bootstrap environment
|
- name: Bootstrap environment
|
||||||
uses: ./.github/actions/bootstrap
|
uses: ./.github/actions/bootstrap
|
||||||
@@ -29,54 +29,15 @@ jobs:
|
|||||||
Unit-Test:
|
Unit-Test:
|
||||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||||
name: "Unit tests"
|
name: "Unit tests"
|
||||||
runs-on: ubuntu-20.04
|
# we need more storage than what's on the default runner
|
||||||
|
runs-on: ubuntu-22.04-4core-16gb
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
- name: Bootstrap environment
|
- name: Bootstrap environment
|
||||||
uses: ./.github/actions/bootstrap
|
uses: ./.github/actions/bootstrap
|
||||||
|
|
||||||
- name: Restore file executable test-fixture cache
|
|
||||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
|
||||||
with:
|
with:
|
||||||
path: syft/file/cataloger/executable/test-fixtures/elf/bin
|
download-test-fixture-cache: true
|
||||||
key: ${{ runner.os }}-unit-file-executable-elf-cache-${{ hashFiles( 'syft/file/cataloger/executable/test-fixtures/elf/cache.fingerprint' ) }}
|
|
||||||
|
|
||||||
- name: Restore file executable shared-info test-fixture cache
|
|
||||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
|
||||||
with:
|
|
||||||
path: syft/file/cataloger/executable/test-fixtures/shared-info/bin
|
|
||||||
key: ${{ runner.os }}-unit-file-executable-shared-info-cache-${{ hashFiles( 'syft/file/cataloger/executable/test-fixtures/shared-info/cache.fingerprint' ) }}
|
|
||||||
|
|
||||||
- name: Restore Java test-fixture cache
|
|
||||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
|
||||||
with:
|
|
||||||
path: syft/pkg/cataloger/java/test-fixtures/java-builds/packages
|
|
||||||
key: ${{ runner.os }}-unit-java-cache-${{ hashFiles( 'syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint' ) }}
|
|
||||||
|
|
||||||
- name: Restore RPM test-fixture cache
|
|
||||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
|
||||||
with:
|
|
||||||
path: syft/pkg/cataloger/redhat/test-fixtures/rpms
|
|
||||||
key: ${{ runner.os }}-unit-rpm-cache-${{ hashFiles( 'syft/pkg/cataloger/redhat/test-fixtures/rpms.fingerprint' ) }}
|
|
||||||
|
|
||||||
- name: Restore go binary test-fixture cache
|
|
||||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
|
||||||
with:
|
|
||||||
path: syft/pkg/cataloger/golang/test-fixtures/archs/binaries
|
|
||||||
key: ${{ runner.os }}-unit-go-binaries-cache-${{ hashFiles( 'syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint' ) }}
|
|
||||||
|
|
||||||
- name: Restore binary cataloger test-fixture cache
|
|
||||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
|
||||||
with:
|
|
||||||
path: syft/pkg/cataloger/binary/test-fixtures/classifiers/bin
|
|
||||||
key: ${{ runner.os }}-unit-binary-cataloger-cache-${{ hashFiles( 'syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint' ) }}
|
|
||||||
|
|
||||||
- name: Restore Kernel test-fixture cache
|
|
||||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
|
||||||
with:
|
|
||||||
path: syft/pkg/cataloger/kernel/test-fixtures/cache
|
|
||||||
key: ${{ runner.os }}-unit-kernel-cache-${{ hashFiles( 'syft/pkg/cataloger/kernel/test-fixtures/cache.fingerprint' ) }}
|
|
||||||
|
|
||||||
- name: Run unit tests
|
- name: Run unit tests
|
||||||
run: make unit
|
run: make unit
|
||||||
@@ -85,31 +46,27 @@ jobs:
|
|||||||
Integration-Test:
|
Integration-Test:
|
||||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||||
name: "Integration tests"
|
name: "Integration tests"
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
- name: Bootstrap environment
|
- name: Bootstrap environment
|
||||||
uses: ./.github/actions/bootstrap
|
uses: ./.github/actions/bootstrap
|
||||||
|
with:
|
||||||
|
download-test-fixture-cache: true
|
||||||
|
|
||||||
- name: Validate syft output against the CycloneDX schema
|
- name: Validate syft output against the CycloneDX schema
|
||||||
run: make validate-cyclonedx-schema
|
run: make validate-cyclonedx-schema
|
||||||
|
|
||||||
- name: Restore integration test cache
|
|
||||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/cmd/syft/internal/test/integration/test-fixtures/cache
|
|
||||||
key: ${{ runner.os }}-integration-test-cache-${{ hashFiles('/cmd/syft/internal/test/integration/test-fixtures/cache.fingerprint') }}
|
|
||||||
|
|
||||||
- name: Run integration tests
|
- name: Run integration tests
|
||||||
run: make integration
|
run: make integration
|
||||||
|
|
||||||
|
|
||||||
Build-Snapshot-Artifacts:
|
Build-Snapshot-Artifacts:
|
||||||
name: "Build snapshot artifacts"
|
name: "Build snapshot artifacts"
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
- name: Bootstrap environment
|
- name: Bootstrap environment
|
||||||
uses: ./.github/actions/bootstrap
|
uses: ./.github/actions/bootstrap
|
||||||
@@ -122,7 +79,7 @@ jobs:
|
|||||||
# why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach).
|
# 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
|
# see https://github.com/actions/upload-artifact/issues/199 for more info
|
||||||
- name: Upload snapshot artifacts
|
- name: Upload snapshot artifacts
|
||||||
uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3
|
||||||
with:
|
with:
|
||||||
# we need to preserve the snapshot data itself as well as the task data that confirms if the
|
# 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
|
# snapshot build is stale or not. Otherwise the downstream jobs will attempt to rebuild the snapshot
|
||||||
@@ -133,20 +90,77 @@ jobs:
|
|||||||
key: snapshot-build-${{ github.run_id }}
|
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@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
|
- name: Bootstrap environment
|
||||||
|
uses: ./.github/actions/bootstrap
|
||||||
|
with:
|
||||||
|
download-test-fixture-cache: true
|
||||||
|
|
||||||
|
- name: Download snapshot build
|
||||||
|
id: snapshot-cache
|
||||||
|
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3
|
||||||
|
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:
|
Acceptance-Linux:
|
||||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||||
name: "Acceptance tests (Linux)"
|
name: "Acceptance tests (Linux)"
|
||||||
needs: [Build-Snapshot-Artifacts]
|
needs: [Build-Snapshot-Artifacts]
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
- name: Bootstrap environment
|
- name: Bootstrap environment
|
||||||
uses: ./.github/actions/bootstrap
|
uses: ./.github/actions/bootstrap
|
||||||
|
with:
|
||||||
|
download-test-fixture-cache: true
|
||||||
|
|
||||||
- name: Download snapshot build
|
- name: Download snapshot build
|
||||||
id: snapshot-cache
|
id: snapshot-cache
|
||||||
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
snapshot
|
snapshot
|
||||||
@@ -162,13 +176,6 @@ jobs:
|
|||||||
- name: Run comparison tests (Linux)
|
- name: Run comparison tests (Linux)
|
||||||
run: make compare-linux
|
run: make compare-linux
|
||||||
|
|
||||||
- name: Restore install.sh test image cache
|
|
||||||
id: install-test-image-cache
|
|
||||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
|
||||||
with:
|
|
||||||
path: ${{ github.workspace }}/test/install/cache
|
|
||||||
key: ${{ runner.os }}-install-test-image-cache-${{ hashFiles('test/install/cache.fingerprint') }}
|
|
||||||
|
|
||||||
- name: Load test image cache
|
- name: Load test image cache
|
||||||
if: steps.install-test-image-cache.outputs.cache-hit == 'true'
|
if: steps.install-test-image-cache.outputs.cache-hit == 'true'
|
||||||
run: make install-test-cache-load
|
run: make install-test-cache-load
|
||||||
@@ -187,18 +194,21 @@ jobs:
|
|||||||
needs: [Build-Snapshot-Artifacts]
|
needs: [Build-Snapshot-Artifacts]
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- name: Install Cosign
|
||||||
|
uses: sigstore/cosign-installer@v3.8.2
|
||||||
|
|
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
- name: Bootstrap environment
|
- name: Bootstrap environment
|
||||||
uses: ./.github/actions/bootstrap
|
uses: ./.github/actions/bootstrap
|
||||||
with:
|
with:
|
||||||
bootstrap-apt-packages: ""
|
bootstrap-apt-packages: ""
|
||||||
compute-fingerprints: "false"
|
|
||||||
go-dependencies: false
|
go-dependencies: false
|
||||||
|
download-test-fixture-cache: true
|
||||||
|
|
||||||
- name: Download snapshot build
|
- name: Download snapshot build
|
||||||
id: snapshot-cache
|
id: snapshot-cache
|
||||||
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
snapshot
|
snapshot
|
||||||
@@ -211,13 +221,6 @@ jobs:
|
|||||||
if: steps.snapshot-cache.outputs.cache-hit != 'true'
|
if: steps.snapshot-cache.outputs.cache-hit != 'true'
|
||||||
run: echo "unable to download snapshots from previous job" && false
|
run: echo "unable to download snapshots from previous job" && false
|
||||||
|
|
||||||
- name: Restore docker image cache for compare testing
|
|
||||||
id: mac-compare-testing-cache
|
|
||||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
|
||||||
with:
|
|
||||||
path: image.tar
|
|
||||||
key: ${{ runner.os }}-${{ hashFiles('test/compare/mac.sh') }}
|
|
||||||
|
|
||||||
- name: Run comparison tests (Mac)
|
- name: Run comparison tests (Mac)
|
||||||
run: make compare-mac
|
run: make compare-mac
|
||||||
|
|
||||||
@@ -229,22 +232,18 @@ jobs:
|
|||||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||||
name: "CLI tests (Linux)"
|
name: "CLI tests (Linux)"
|
||||||
needs: [Build-Snapshot-Artifacts]
|
needs: [Build-Snapshot-Artifacts]
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 #v4.1.6
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
- name: Bootstrap environment
|
- name: Bootstrap environment
|
||||||
uses: ./.github/actions/bootstrap
|
uses: ./.github/actions/bootstrap
|
||||||
|
|
||||||
- name: Restore CLI test-fixture cache
|
|
||||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
|
||||||
with:
|
with:
|
||||||
path: ${{ github.workspace }}/test/cli/test-fixtures/cache
|
download-test-fixture-cache: true
|
||||||
key: ${{ runner.os }}-cli-test-cache-${{ hashFiles('test/cli/test-fixtures/cache.fingerprint') }}
|
|
||||||
|
|
||||||
- name: Download snapshot build
|
- name: Download snapshot build
|
||||||
id: snapshot-cache
|
id: snapshot-cache
|
||||||
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 #v4.0.2
|
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
snapshot
|
snapshot
|
||||||
@@ -259,3 +258,23 @@ jobs:
|
|||||||
|
|
||||||
- name: Run CLI Tests (Linux)
|
- name: Run CLI Tests (Linux)
|
||||||
run: make cli
|
run: make cli
|
||||||
|
|
||||||
|
|
||||||
|
Cleanup-Cache:
|
||||||
|
name: "Cleanup snapshot cache"
|
||||||
|
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
permissions:
|
||||||
|
actions: write
|
||||||
|
needs:
|
||||||
|
- Acceptance-Linux
|
||||||
|
- Acceptance-Mac
|
||||||
|
- Cli-Linux
|
||||||
|
- Upload-Snapshot-Artifacts
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
||||||
|
|
||||||
|
- name: Delete snapshot cache
|
||||||
|
run: gh cache delete "snapshot-build-${{ github.run_id }}"
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
|||||||
+42
-31
@@ -1,53 +1,36 @@
|
|||||||
issues:
|
version: "2"
|
||||||
max-same-issues: 25
|
run:
|
||||||
|
tests: 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
|
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
|
default: none
|
||||||
disable-all: true
|
|
||||||
enable:
|
enable:
|
||||||
- asciicheck
|
- asciicheck
|
||||||
- bodyclose
|
- bodyclose
|
||||||
|
- copyloopvar
|
||||||
- dogsled
|
- dogsled
|
||||||
- dupl
|
- dupl
|
||||||
- errcheck
|
- errcheck
|
||||||
- exportloopref
|
|
||||||
- funlen
|
- funlen
|
||||||
- gocognit
|
- gocognit
|
||||||
- goconst
|
- goconst
|
||||||
- gocritic
|
- gocritic
|
||||||
- gocyclo
|
- gocyclo
|
||||||
- gofmt
|
|
||||||
- goimports
|
|
||||||
- goprintffuncname
|
- goprintffuncname
|
||||||
- gosec
|
- gosec
|
||||||
- gosimple
|
|
||||||
- govet
|
- govet
|
||||||
- ineffassign
|
- ineffassign
|
||||||
- misspell
|
- misspell
|
||||||
- nakedret
|
- nakedret
|
||||||
|
- nolintlint
|
||||||
- revive
|
- revive
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- stylecheck
|
|
||||||
- typecheck
|
|
||||||
- unconvert
|
- unconvert
|
||||||
- unparam
|
- unparam
|
||||||
- unused
|
- unused
|
||||||
- whitespace
|
- whitespace
|
||||||
|
settings:
|
||||||
linters-settings:
|
|
||||||
funlen:
|
funlen:
|
||||||
# Checks the number of lines in a function.
|
|
||||||
# If lower than 0, disable the check.
|
|
||||||
# Default: 60
|
|
||||||
lines: 70
|
lines: 70
|
||||||
# Checks the number of statements in a function.
|
|
||||||
# If lower than 0, disable the check.
|
|
||||||
# Default: 40
|
|
||||||
statements: 50
|
statements: 50
|
||||||
gocritic:
|
gocritic:
|
||||||
enabled-checks:
|
enabled-checks:
|
||||||
@@ -55,12 +38,21 @@ linters-settings:
|
|||||||
- ruleguard
|
- ruleguard
|
||||||
settings:
|
settings:
|
||||||
ruleguard:
|
ruleguard:
|
||||||
rules: "test/rules/rules.go"
|
rules: test/rules/rules.go
|
||||||
output:
|
gosec:
|
||||||
uniq-by-line: false
|
excludes:
|
||||||
run:
|
- G115
|
||||||
timeout: 10m
|
exclusions:
|
||||||
tests: false
|
generated: lax
|
||||||
|
presets:
|
||||||
|
- comments
|
||||||
|
- common-false-positives
|
||||||
|
- legacy
|
||||||
|
- std-error-handling
|
||||||
|
paths:
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
||||||
|
|
||||||
# do not enable...
|
# do not enable...
|
||||||
# - deadcode # The owner seems to have abandoned the linter. Replaced by "unused".
|
# - deadcode # The owner seems to have abandoned the linter. Replaced by "unused".
|
||||||
@@ -80,7 +72,6 @@ run:
|
|||||||
# - lll # without a way to specify per-line exception cases, this is not usable
|
# - lll # without a way to specify per-line exception cases, this is not usable
|
||||||
# - maligned # this is an excellent linter, but tricky to optimize and we are not sensitive to memory layout optimizations
|
# - maligned # this is an excellent linter, but tricky to optimize and we are not sensitive to memory layout optimizations
|
||||||
# - nestif
|
# - nestif
|
||||||
# - nolintlint # as of go1.19 this conflicts with the behavior of gofmt, which is a deal-breaker (lint-fix will still fail when running lint)
|
|
||||||
# - prealloc # following this rule isn't consistently a good idea, as it sometimes forces unnecessary allocations that result in less idiomatic code
|
# - prealloc # following this rule isn't consistently a good idea, as it sometimes forces unnecessary allocations that result in less idiomatic code
|
||||||
# - rowserrcheck # not in a repo with sql, so this is not useful
|
# - rowserrcheck # not in a repo with sql, so this is not useful
|
||||||
# - scopelint # deprecated
|
# - scopelint # deprecated
|
||||||
@@ -88,3 +79,23 @@ run:
|
|||||||
# - testpackage
|
# - testpackage
|
||||||
# - varcheck # The owner seems to have abandoned the linter. Replaced by "unused".
|
# - 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)
|
# - 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$
|
||||||
|
|||||||
+3
-1
@@ -1,3 +1,5 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
release:
|
release:
|
||||||
prerelease: auto
|
prerelease: auto
|
||||||
draft: false
|
draft: false
|
||||||
@@ -80,7 +82,7 @@ nfpms:
|
|||||||
- deb
|
- deb
|
||||||
|
|
||||||
brews:
|
brews:
|
||||||
- tap:
|
- repository:
|
||||||
owner: anchore
|
owner: anchore
|
||||||
name: homebrew-syft
|
name: homebrew-syft
|
||||||
token: "{{.Env.GITHUB_BREW_TOKEN}}"
|
token: "{{.Env.GITHUB_BREW_TOKEN}}"
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, religion, or sexual identity
|
||||||
|
and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness toward other people
|
||||||
|
* Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the
|
||||||
|
overall community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery, and sexual attention or
|
||||||
|
advances of any kind
|
||||||
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email
|
||||||
|
address, without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement at
|
||||||
|
[opensource@anchore.com](mailto:opensource@anchore.com).
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series
|
||||||
|
of actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or
|
||||||
|
permanent ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within
|
||||||
|
the community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.0, available at
|
||||||
|
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||||
|
enforcement ladder](https://github.com/mozilla/diversity).
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
https://www.contributor-covenant.org/faq. Translations are available at
|
||||||
|
https://www.contributor-covenant.org/translations.
|
||||||
@@ -9,3 +9,7 @@ A cataloger contributed by Oracle Corporation that extracts packages given withi
|
|||||||
## Swift Package Manager
|
## Swift Package Manager
|
||||||
|
|
||||||
A cataloger contributed by Axis Communications that catalogs packages resolved by 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.
|
||||||
|
|||||||
+15
-5
@@ -83,7 +83,7 @@ Syft's core library is implemented in the `syft` package and subpackages, where
|
|||||||
- the `syft` package contains a single function that can take a `source.Source` object and catalog it, producing an `sbom.SBOM` object
|
- the `syft` package contains a single function that can take a `source.Source` object and catalog it, producing an `sbom.SBOM` object
|
||||||
- the `syft/format` package contains the ability to encode and decode SBOMs to and from different SBOM formats (such as SPDX and CycloneDX)
|
- the `syft/format` package contains the ability to encode and decode SBOMs to and from different SBOM formats (such as SPDX and CycloneDX)
|
||||||
|
|
||||||
The `cmd` pacakge at the highest level execution flow wires up [`spf13/cobra`](https://github.com/spf13/cobra) commands for execution in the main application:
|
The `cmd` package at the highest level execution flow wires up [`spf13/cobra`](https://github.com/spf13/cobra) commands for execution in the main application:
|
||||||
```mermaid
|
```mermaid
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
participant main as cmd/syft/main
|
participant main as cmd/syft/main
|
||||||
@@ -212,7 +212,7 @@ Finally, here is an example of where the package construction is done within the
|
|||||||
- [The APK package constructor itself](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/package.go#L12-L27)
|
- [The APK package constructor itself](https://github.com/anchore/syft/tree/v0.70.0/syft/pkg/cataloger/apkdb/package.go#L12-L27)
|
||||||
|
|
||||||
Interested in building a new cataloger? Checkout the [list of issues with the `new-cataloger` label](https://github.com/anchore/syft/issues?q=is%3Aopen+is%3Aissue+label%3Anew-cataloger+no%3Aassignee)!
|
Interested in building a new cataloger? Checkout the [list of issues with the `new-cataloger` label](https://github.com/anchore/syft/issues?q=is%3Aopen+is%3Aissue+label%3Anew-cataloger+no%3Aassignee)!
|
||||||
If you have questions about implementing a cataloger feel free to file an issue or reach out to us [on slack](https://anchore.com/slack)!
|
If you have questions about implementing a cataloger feel free to file an issue or reach out to us [on discourse](https://anchore.com/discourse)!
|
||||||
|
|
||||||
|
|
||||||
#### Searching for files
|
#### Searching for files
|
||||||
@@ -227,6 +227,16 @@ rough outline how that works:
|
|||||||
|
|
||||||
## Testing
|
## 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
|
### Levels of testing
|
||||||
|
|
||||||
- `unit`: The default level of test which is distributed throughout the repo are unit tests. Any `_test.go` file that
|
- `unit`: The default level of test which is distributed throughout the repo are unit tests. Any `_test.go` file that
|
||||||
@@ -367,11 +377,11 @@ package under test and should always be updated by invoking `go test` on the spe
|
|||||||
update flag provided.
|
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
|
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. For instance, at the time of this writing
|
compares that SBOM with what is generated from the latest presenter code. The following command can be used to
|
||||||
the CycloneDX presenter snapshots can be updated by running:
|
update the golden files for the various snapshot tests:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go test ./internal/formats -update-cyclonedx
|
make update-format-golden-files
|
||||||
```
|
```
|
||||||
|
|
||||||
These flags are defined at the top of the test files that have tests that use the snapshot files.
|
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-debian11:debug@sha256:a0a404776dec98be120089ae42bbdfbe48c177921d856937d124d48eb8c0b951 AS build
|
FROM gcr.io/distroless/static-debian12:latest AS build
|
||||||
|
|
||||||
FROM scratch
|
FROM scratch
|
||||||
# needed for version check HTTPS request
|
# needed for version check HTTPS request
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
FROM gcr.io/distroless/static-debian11:debug@sha256:a0a404776dec98be120089ae42bbdfbe48c177921d856937d124d48eb8c0b951
|
FROM gcr.io/distroless/static-debian12:debug
|
||||||
|
|
||||||
# create the /tmp dir, which is needed for image content cache
|
# create the /tmp dir, which is needed for image content cache
|
||||||
WORKDIR /tmp
|
WORKDIR /tmp
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ ci-bootstrap-go:
|
|||||||
|
|
||||||
# this is a bootstrapping catch-all, where if the target doesn't exist, we'll ensure the tools are installed and then try again
|
# this is a bootstrapping catch-all, where if the target doesn't exist, we'll ensure the tools are installed and then try again
|
||||||
%:
|
%:
|
||||||
make $(TASK)
|
@make --silent $(TASK)
|
||||||
$(TASK) $@
|
@$(TASK) $@
|
||||||
|
|
||||||
## Shim targets #################################
|
## Shim targets #################################
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,9 @@
|
|||||||
<a href="https://goreportcard.com/report/github.com/anchore/syft" target="_blank"><img alt="Go Report Card" src="https://goreportcard.com/badge/github.com/anchore/syft"></a>
|
<a href="https://goreportcard.com/report/github.com/anchore/syft" target="_blank"><img alt="Go Report Card" src="https://goreportcard.com/badge/github.com/anchore/syft"></a>
|
||||||
<a href="https://github.com/anchore/syft/releases/latest" target="_blank"><img alt="GitHub release" src="https://img.shields.io/github/release/anchore/syft.svg"></a>
|
<a href="https://github.com/anchore/syft/releases/latest" target="_blank"><img alt="GitHub release" src="https://img.shields.io/github/release/anchore/syft.svg"></a>
|
||||||
<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="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="" 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/slack" target="_blank"><img alt="Slack" src="https://img.shields.io/badge/Slack-Join-blue?logo=slack"></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>
|
</p>
|
||||||
|
|
||||||

|

|
||||||
@@ -40,11 +41,10 @@ Syft binaries are provided for Linux, macOS and Windows.
|
|||||||
> curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
|
> curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
... or, you can specify a release version and destination directory for the installation:
|
Install script options:
|
||||||
|
- `-b`: Specify a custom installation directory (defaults to `./bin`)
|
||||||
> ```bash
|
- `-d`: More verbose logging levels (`-d` for debug, `-dd` for trace)
|
||||||
> curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b <DESTINATION_DIR> <RELEASE_VERSION>
|
- `-v`: Verify the signature of the downloaded artifact before installation (requires [`cosign`](https://github.com/sigstore/cosign) to be installed)
|
||||||
> ```
|
|
||||||
|
|
||||||
### Homebrew
|
### Homebrew
|
||||||
```bash
|
```bash
|
||||||
@@ -67,7 +67,7 @@ choco install syft -y
|
|||||||
|
|
||||||
### Nix
|
### Nix
|
||||||
|
|
||||||
**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`.
|
**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`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
nix-env -i syft
|
nix-env -i syft
|
||||||
@@ -106,8 +106,10 @@ syft <image> -o <format>
|
|||||||
Where the `formats` available are:
|
Where the `formats` available are:
|
||||||
- `syft-json`: Use this to get as much information out of Syft as possible!
|
- `syft-json`: Use this to get as much information out of Syft as possible!
|
||||||
- `syft-text`: A row-oriented, human-and-machine-friendly output.
|
- `syft-text`: A row-oriented, human-and-machine-friendly output.
|
||||||
- `cyclonedx-xml`: A XML report conforming to the [CycloneDX 1.4 specification](https://cyclonedx.org/specification/overview/).
|
- `cyclonedx-xml`: A XML report conforming to the [CycloneDX 1.6 specification](https://cyclonedx.org/specification/overview/).
|
||||||
- `cyclonedx-json`: A JSON report conforming to the [CycloneDX 1.4 specification](https://cyclonedx.org/specification/overview/).
|
- `cyclonedx-xml@1.5`: A XML report conforming to the [CycloneDX 1.5 specification](https://cyclonedx.org/specification/overview/).
|
||||||
|
- `cyclonedx-json`: A JSON report conforming to the [CycloneDX 1.6 specification](https://cyclonedx.org/specification/overview/).
|
||||||
|
- `cyclonedx-json@1.5`: A JSON report conforming to the [CycloneDX 1.5 specification](https://cyclonedx.org/specification/overview/).
|
||||||
- `spdx-tag-value`: A tag-value formatted report conforming to the [SPDX 2.3 specification](https://spdx.github.io/spdx-spec/v2.3/).
|
- `spdx-tag-value`: A tag-value formatted report conforming to the [SPDX 2.3 specification](https://spdx.github.io/spdx-spec/v2.3/).
|
||||||
- `spdx-tag-value@2.2`: A tag-value formatted report conforming to the [SPDX 2.2 specification](https://spdx.github.io/spdx-spec/v2.2.2/).
|
- `spdx-tag-value@2.2`: A tag-value formatted report conforming to the [SPDX 2.2 specification](https://spdx.github.io/spdx-spec/v2.2.2/).
|
||||||
- `spdx-json`: A JSON report conforming to the [SPDX 2.3 JSON Schema](https://github.com/spdx/spdx-spec/blob/v2.3/schemas/spdx-schema.json).
|
- `spdx-json`: A JSON report conforming to the [SPDX 2.3 JSON Schema](https://github.com/spdx/spdx-spec/blob/v2.3/schemas/spdx-schema.json).
|
||||||
@@ -116,9 +118,12 @@ Where the `formats` available are:
|
|||||||
- `syft-table`: A columnar summary (default).
|
- `syft-table`: A columnar summary (default).
|
||||||
- `template`: Lets the user specify the output format. See ["Using templates"](#using-templates) below.
|
- `template`: Lets the user specify the output format. See ["Using templates"](#using-templates) below.
|
||||||
|
|
||||||
|
Note that flags using the @<version> can be used for earlier versions of each specification as well.
|
||||||
|
|
||||||
### Supported Ecosystems
|
### Supported Ecosystems
|
||||||
|
|
||||||
- Alpine (apk)
|
- Alpine (apk)
|
||||||
|
- Bitnami packages
|
||||||
- C (conan)
|
- C (conan)
|
||||||
- C++ (conan)
|
- C++ (conan)
|
||||||
- Dart (pubs)
|
- Dart (pubs)
|
||||||
@@ -135,13 +140,14 @@ Where the `formats` available are:
|
|||||||
- Linux kernel archives (vmlinz)
|
- Linux kernel archives (vmlinz)
|
||||||
- Linux kernel modules (ko)
|
- Linux kernel modules (ko)
|
||||||
- Nix (outputs in /nix/store)
|
- Nix (outputs in /nix/store)
|
||||||
- PHP (composer)
|
- PHP (composer, PECL, Pear)
|
||||||
- Python (wheel, egg, poetry, requirements.txt)
|
- Python (wheel, egg, poetry, requirements.txt)
|
||||||
- Red Hat (rpm)
|
- Red Hat (rpm)
|
||||||
- Ruby (gem)
|
- Ruby (gem)
|
||||||
- Rust (cargo.lock)
|
- Rust (cargo.lock, auditable binary)
|
||||||
- Swift (cocoapods, swift-package-manager)
|
- Swift (cocoapods, swift-package-manager)
|
||||||
- Wordpress plugins
|
- Wordpress plugins
|
||||||
|
- Terraform providers (.terraform.lock.hcl)
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
@@ -165,9 +171,17 @@ Our [wiki](https://github.com/anchore/syft/wiki) contains further details on the
|
|||||||
* [Adding an SBOM to an image as an attestation using Syft](https://github.com/anchore/syft/wiki/attestation#adding-an-sbom-to-an-image-as-an-attestation-using-syft)
|
* [Adding an SBOM to an image as an attestation using Syft](https://github.com/anchore/syft/wiki/attestation#adding-an-sbom-to-an-image-as-an-attestation-using-syft)
|
||||||
* [Configuration](https://github.com/anchore/syft/wiki/configuration)
|
* [Configuration](https://github.com/anchore/syft/wiki/configuration)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Check out our [contributing](/CONTRIBUTING.md) guide and [developer](/DEVELOPING.md) docs.
|
||||||
|
|
||||||
## Syft Team Meetings
|
## Syft Team Meetings
|
||||||
|
|
||||||
The Syft Team hold regular community meetings online. All are welcome to join to bring topics for discussion.
|
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.
|
- 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))
|
- 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!
|
- 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>
|
||||||
|
|||||||
+12
-85
@@ -1,5 +1,16 @@
|
|||||||
# Release
|
# 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
|
## Creating a release
|
||||||
|
|
||||||
This release process itself should be as automated as possible, and has only a few steps:
|
This release process itself should be as automated as possible, and has only a few steps:
|
||||||
@@ -9,15 +20,9 @@ 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
|
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.
|
re-run the release trigger command.
|
||||||
|
|
||||||
1. A release admin must approve the release on the GitHub Actions release pipeline run page.
|
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.
|
||||||
Once approved, the release pipeline will generate all assets and publish a GitHub Release.
|
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
|
## Retracting a release
|
||||||
|
|
||||||
@@ -32,81 +37,3 @@ 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
|
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).
|
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.
|
|
||||||
|
|||||||
+226
-60
@@ -4,9 +4,19 @@ vars:
|
|||||||
OWNER: anchore
|
OWNER: anchore
|
||||||
PROJECT: syft
|
PROJECT: syft
|
||||||
|
|
||||||
|
CACHE_IMAGE: ghcr.io/{{ .OWNER }}/{{ .PROJECT }}/test-fixture-cache:latest
|
||||||
|
|
||||||
# static file dirs
|
# static file dirs
|
||||||
TOOL_DIR: .tool
|
TOOL_DIR: .tool
|
||||||
TMP_DIR: .tmp
|
TMP_DIR: .tmp
|
||||||
|
ORAS_CACHE: "{{ .TMP_DIR }}/oras-cache"
|
||||||
|
CACHE_PATHS_FILE: "{{ .TMP_DIR }}/cache_paths.json"
|
||||||
|
LAST_CACHE_PULL_FILE: "{{ .TMP_DIR }}/last_cache_paths.json"
|
||||||
|
|
||||||
|
# TOOLS
|
||||||
|
ORAS: "{{ .TOOL_DIR }}/oras"
|
||||||
|
YQ: "{{ .TOOL_DIR }}/yq"
|
||||||
|
TASK: "{{ .TOOL_DIR }}/task"
|
||||||
|
|
||||||
# used for changelog generation
|
# used for changelog generation
|
||||||
CHANGELOG: CHANGELOG.md
|
CHANGELOG: CHANGELOG.md
|
||||||
@@ -17,7 +27,7 @@ vars:
|
|||||||
sh: uname -s | tr '[:upper:]' '[:lower:]'
|
sh: uname -s | tr '[:upper:]' '[:lower:]'
|
||||||
ARCH:
|
ARCH:
|
||||||
sh: |
|
sh: |
|
||||||
[ "$(uname -m)" = "x86_64" ] && echo "amd64_v1" || echo $(uname -m)
|
[ "$(uname -m)" = "x86_64" ] && echo "amd64_v1" || { [ "$(uname -m)" = "aarch64" ] && echo "arm64_v8.0" || echo $(uname -m); }
|
||||||
PROJECT_ROOT:
|
PROJECT_ROOT:
|
||||||
sh: echo $PWD
|
sh: echo $PWD
|
||||||
# note: the snapshot dir must be a relative path starting with ./
|
# note: the snapshot dir must be a relative path starting with ./
|
||||||
@@ -33,6 +43,9 @@ vars:
|
|||||||
COMPARE_DIR: ./test/compare
|
COMPARE_DIR: ./test/compare
|
||||||
COMPARE_TEST_IMAGE: centos:8.2.2004
|
COMPARE_TEST_IMAGE: centos:8.2.2004
|
||||||
|
|
||||||
|
env:
|
||||||
|
GNUMAKEFLAGS: '--no-print-directory'
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
|
|
||||||
## High-level tasks #################################
|
## High-level tasks #################################
|
||||||
@@ -62,9 +75,9 @@ tasks:
|
|||||||
- task: unit
|
- task: unit
|
||||||
- task: integration
|
- task: integration
|
||||||
- task: validate-cyclonedx-schema
|
- task: validate-cyclonedx-schema
|
||||||
- task: benchmark
|
|
||||||
- task: test-utils
|
- task: test-utils
|
||||||
- task: cli
|
- task: cli
|
||||||
|
- task: check-docker-cache
|
||||||
|
|
||||||
## Bootstrap tasks #################################
|
## Bootstrap tasks #################################
|
||||||
|
|
||||||
@@ -177,6 +190,14 @@ tasks:
|
|||||||
|
|
||||||
|
|
||||||
## Testing 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:
|
unit:
|
||||||
desc: Run unit tests
|
desc: Run unit tests
|
||||||
@@ -199,10 +220,11 @@ tasks:
|
|||||||
cmds:
|
cmds:
|
||||||
- "go test -v ./cmd/syft/internal/test/integration"
|
- "go test -v ./cmd/syft/internal/test/integration"
|
||||||
# exercise most of the CLI with the data race detector
|
# exercise most of the CLI with the data race detector
|
||||||
- "go run -race cmd/syft/main.go alpine:latest"
|
# 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"
|
||||||
|
|
||||||
validate-cyclonedx-schema:
|
validate-cyclonedx-schema:
|
||||||
desc: Run integration tests
|
desc: Validate that Syft produces valid CycloneDX documents
|
||||||
cmds:
|
cmds:
|
||||||
- "cd schema/cyclonedx && make"
|
- "cd schema/cyclonedx && make"
|
||||||
|
|
||||||
@@ -212,15 +234,10 @@ tasks:
|
|||||||
# that the cache being restored with the correct binary will be rebuilt since the timestamps
|
# that the cache being restored with the correct binary will be rebuilt since the timestamps
|
||||||
# and local checksums will not line up.
|
# and local checksums will not line up.
|
||||||
deps: [tools, snapshot]
|
deps: [tools, snapshot]
|
||||||
sources:
|
|
||||||
- "{{ .SNAPSHOT_BIN }}"
|
|
||||||
- ./test/cli/**
|
|
||||||
- ./**/*.go
|
|
||||||
cmds:
|
cmds:
|
||||||
- cmd: "echo 'testing binary: {{ .SNAPSHOT_BIN }}'"
|
- cmd: "echo 'testing binary: {{ .SNAPSHOT_BIN }}'"
|
||||||
silent: true
|
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
|
silent: true
|
||||||
|
|
||||||
- "go test -count=1 -timeout=15m -v ./test/cli"
|
- "go test -count=1 -timeout=15m -v ./test/cli"
|
||||||
@@ -229,18 +246,14 @@ tasks:
|
|||||||
|
|
||||||
test-utils:
|
test-utils:
|
||||||
desc: Run tests for pipeline utils
|
desc: Run tests for pipeline utils
|
||||||
sources:
|
|
||||||
- .github/scripts/labeler*.py
|
|
||||||
cmds:
|
cmds:
|
||||||
- cmd: python .github/scripts/labeler_test.py
|
- cmd: .github/scripts/labeler_test.py
|
||||||
|
|
||||||
|
|
||||||
## Benchmark test targets #################################
|
## Benchmark test targets #################################
|
||||||
|
|
||||||
benchmark:
|
benchmark:
|
||||||
deps: [tmpdir]
|
deps: [tmpdir]
|
||||||
sources:
|
|
||||||
- ./**/*.go
|
|
||||||
generates:
|
generates:
|
||||||
- "{{ .TMP_DIR }}/benchmark-main.txt"
|
- "{{ .TMP_DIR }}/benchmark-main.txt"
|
||||||
cmds:
|
cmds:
|
||||||
@@ -253,8 +266,6 @@ tasks:
|
|||||||
|
|
||||||
show-benchstat:
|
show-benchstat:
|
||||||
deps: [benchmark, tmpdir]
|
deps: [benchmark, tmpdir]
|
||||||
sources:
|
|
||||||
- "{{ .TMP_DIR }}/benchstat.txt"
|
|
||||||
cmds:
|
cmds:
|
||||||
- cmd: "cat {{ .TMP_DIR }}/benchstat.txt"
|
- cmd: "cat {{ .TMP_DIR }}/benchstat.txt"
|
||||||
silent: true
|
silent: true
|
||||||
@@ -263,56 +274,188 @@ tasks:
|
|||||||
## Test-fixture-related targets #################################
|
## Test-fixture-related targets #################################
|
||||||
|
|
||||||
fingerprints:
|
fingerprints:
|
||||||
desc: Generate test fixture fingerprints
|
desc: Generate fingerprints for all non-docker test fixture
|
||||||
|
silent: true
|
||||||
|
# this will look for `test-fixtures/Makefile` and invoke the `fingerprint` target to calculate all cache input fingerprint files
|
||||||
generates:
|
generates:
|
||||||
- cmd/syft/internal/test/integration/test-fixtures/cache.fingerprint
|
- '**/test-fixtures/**/*.fingerprint'
|
||||||
- syft/file/cataloger/executable/test-fixtures/elf/cache.fingerprint
|
|
||||||
- syft/file/cataloger/executable/test-fixtures/shared-info/cache.fingerprint
|
|
||||||
- syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint
|
|
||||||
- syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint
|
|
||||||
- syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint
|
|
||||||
- syft/pkg/cataloger/redhat/test-fixtures/rpms.fingerprint
|
|
||||||
- syft/pkg/cataloger/kernel/test-fixtures/cache.fingerprint
|
|
||||||
- test/install/cache.fingerprint
|
- test/install/cache.fingerprint
|
||||||
- test/cli/test-fixtures/cache.fingerprint
|
|
||||||
cmds:
|
cmds:
|
||||||
# for EXECUTABLE unit test fixtures
|
- |
|
||||||
- "cd syft/file/cataloger/executable/test-fixtures/elf && make cache.fingerprint"
|
BOLD='\033[1m'
|
||||||
- "cd syft/file/cataloger/executable/test-fixtures/shared-info && make cache.fingerprint"
|
YELLOW='\033[0;33m'
|
||||||
# for IMAGE integration test fixtures
|
RESET='\033[0m'
|
||||||
- "cd cmd/syft/internal/test/integration/test-fixtures && make cache.fingerprint"
|
|
||||||
# for BINARY unit test fixtures
|
|
||||||
- "cd syft/pkg/cataloger/binary/test-fixtures && make cache.fingerprint"
|
|
||||||
# for JAVA BUILD unit test fixtures
|
|
||||||
- "cd syft/pkg/cataloger/java/test-fixtures/java-builds && make cache.fingerprint"
|
|
||||||
# for GO BINARY unit test fixtures
|
|
||||||
- "cd syft/pkg/cataloger/golang/test-fixtures/archs && make binaries.fingerprint"
|
|
||||||
# for RPM unit test fixtures
|
|
||||||
- "cd syft/pkg/cataloger/redhat/test-fixtures && make rpms.fingerprint"
|
|
||||||
# for Kernel unit test fixtures
|
|
||||||
- "cd syft/pkg/cataloger/kernel/test-fixtures && make cache.fingerprint"
|
|
||||||
# for INSTALL test fixtures
|
|
||||||
- "cd test/install && make cache.fingerprint"
|
|
||||||
# for CLI test fixtures
|
|
||||||
- "cd test/cli/test-fixtures && make cache.fingerprint"
|
|
||||||
|
|
||||||
fixtures:
|
echo -e "${YELLOW}creating fingerprint files for non-docker fixtures...${RESET}"
|
||||||
desc: Generate test fixtures
|
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
|
||||||
|
|
||||||
|
# for debugging...
|
||||||
|
# echo -e "generated all fixture fingerprints"
|
||||||
|
|
||||||
|
- .github/scripts/fingerprint_docker_fixtures.py
|
||||||
|
- |
|
||||||
|
# if DOWNLOAD_TEST_FIXTURE_CACHE is set to 'false', then we don't need to calculate the fingerprint for the cache
|
||||||
|
if [ "$DOWNLOAD_TEST_FIXTURE_CACHE" = "false" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
.github/scripts/find_cache_paths.py {{ .CACHE_PATHS_FILE }} > /dev/null
|
||||||
|
|
||||||
|
|
||||||
|
refresh-fixtures:
|
||||||
|
desc: Clear and fetch all test fixture cache
|
||||||
|
aliases:
|
||||||
|
- fixtures
|
||||||
|
silent: true
|
||||||
|
deps:
|
||||||
|
- tools
|
||||||
cmds:
|
cmds:
|
||||||
- "cd syft/file/cataloger/executable/test-fixtures/elf && make"
|
- |
|
||||||
- "cd syft/file/cataloger/executable/test-fixtures/shared-info && make"
|
BOLD='\033[1m'
|
||||||
- "cd syft/pkg/cataloger/java/test-fixtures/java-builds && make"
|
PURPLE='\033[0;35m'
|
||||||
- "cd syft/pkg/cataloger/redhat/test-fixtures && make"
|
RESET='\033[0m'
|
||||||
- "cd syft/pkg/cataloger/binary/test-fixtures && make"
|
|
||||||
|
# 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
|
||||||
|
echo -e "${BOLD}${PURPLE}empty cache, downloading cache...${RESET}"
|
||||||
|
{{ .TASK }} download-test-fixture-cache
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
{{ .TASK }} fingerprints
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
build-fixtures:
|
||||||
|
desc: Generate all non-docker test fixtures
|
||||||
|
silent: true
|
||||||
|
# this will look for `test-fixtures/Makefile` and invoke the `fixtures` target to generate any and all test fixtures
|
||||||
|
cmds:
|
||||||
|
- |
|
||||||
|
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
|
||||||
|
echo -e "${YELLOW}${BOLD}generating fixtures in $dir${RESET}"
|
||||||
|
(make -C "$dir" fixtures)
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo -e "${BOLD}generated all fixtures${RESET}"
|
||||||
|
|
||||||
|
download-test-fixture-cache:
|
||||||
|
desc: Download test fixture cache from ghcr.io
|
||||||
|
deps: [tools, clean-cache]
|
||||||
|
vars:
|
||||||
|
CACHE_DIGEST:
|
||||||
|
sh: docker manifest inspect {{ .CACHE_IMAGE }} | {{ .YQ }} -r '.annotations.fingerprint'
|
||||||
|
cmds:
|
||||||
|
- silent: true
|
||||||
|
cmd: |
|
||||||
|
# if oras cache is > 4 GB, delete it
|
||||||
|
if [ -d {{ .ORAS_CACHE }} ]; then
|
||||||
|
total_size=$(du -c {{ .ORAS_CACHE }} | grep total | awk '{print $1}')
|
||||||
|
if [ "$total_size" -gt 4194304 ]; then
|
||||||
|
echo 'deleting oras cache'
|
||||||
|
rm -rf {{ .ORAS_CACHE }}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
- "ORAS_CACHE={{ .ORAS_CACHE }} {{ .ORAS }} pull {{ .CACHE_IMAGE }}"
|
||||||
|
- "cp {{ .CACHE_PATHS_FILE }} {{ .LAST_CACHE_PULL_FILE }}"
|
||||||
|
|
||||||
|
upload-test-fixture-cache:
|
||||||
|
desc: Upload the test fixture cache to ghcr.io
|
||||||
|
deps: [tools, fingerprints]
|
||||||
|
silent: true
|
||||||
|
cmd: |
|
||||||
|
set -eu
|
||||||
|
oras_command="{{ .ORAS }} push {{ .CACHE_IMAGE }}"
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
show-test-image-cache:
|
show-test-image-cache:
|
||||||
silent: true
|
silent: true
|
||||||
cmds:
|
cmds:
|
||||||
- "echo '\nDocker daemon cache:'"
|
- "echo 'Docker daemon cache:'"
|
||||||
- "docker images --format '{{`{{.ID}}`}} {{`{{.Repository}}`}}:{{`{{.Tag}}`}}' | grep stereoscope-fixture- | sort"
|
- "docker images --format '{{`{{.ID}}`}} {{`{{.Repository}}`}}:{{`{{.Tag}}`}}' | grep stereoscope-fixture- | sort"
|
||||||
- "echo '\nTar cache:'"
|
- "echo '\nTar cache:'"
|
||||||
- 'find . -type f -wholename "**/test-fixtures/snapshot/*" | sort'
|
- 'find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" | sort'
|
||||||
|
|
||||||
|
check-docker-cache:
|
||||||
|
desc: Ensure docker caches aren't using too much disk space
|
||||||
|
silent: true
|
||||||
|
cmd: |
|
||||||
|
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'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
## install.sh testing targets #################################
|
## install.sh testing targets #################################
|
||||||
|
|
||||||
@@ -438,7 +581,7 @@ tasks:
|
|||||||
- "{{ .NEXT_VERSION }}"
|
- "{{ .NEXT_VERSION }}"
|
||||||
cmds:
|
cmds:
|
||||||
- "{{ .TOOL_DIR }}/chronicle -vv -n --version-file {{ .NEXT_VERSION }} > {{ .CHANGELOG }}"
|
- "{{ .TOOL_DIR }}/chronicle -vv -n --version-file {{ .NEXT_VERSION }} > {{ .CHANGELOG }}"
|
||||||
- "{{ .TOOL_DIR }}/glow {{ .CHANGELOG }}"
|
- "{{ .TOOL_DIR }}/glow -w 0 {{ .CHANGELOG }}"
|
||||||
|
|
||||||
|
|
||||||
## Release targets #################################
|
## Release targets #################################
|
||||||
@@ -489,8 +632,31 @@ tasks:
|
|||||||
- "rm -rf {{ .SNAPSHOT_DIR }}"
|
- "rm -rf {{ .SNAPSHOT_DIR }}"
|
||||||
- "rm -rf {{ .TMP_DIR }}/goreleaser.yaml"
|
- "rm -rf {{ .TMP_DIR }}/goreleaser.yaml"
|
||||||
|
|
||||||
clean-cache:
|
clean-docker-cache:
|
||||||
desc: Remove all docker cache and local image tar cache
|
desc: Remove all docker cache tars and images from the daemon
|
||||||
cmds:
|
cmds:
|
||||||
- 'find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" -delete'
|
- find . -type d -wholename "**/test-fixtures/cache" | xargs rm -rf
|
||||||
- "docker images --format '{{`{{.ID}}`}} {{`{{.Repository}}`}}' | grep stereoscope-fixture- | awk '{print $$1}' | uniq | xargs -r docker rmi --force"
|
- docker images --format '{{`{{.ID}}`}} {{`{{.Repository}}`}}' | grep stereoscope-fixture- | awk '{print $1}' | uniq | xargs -r docker rmi --force
|
||||||
|
|
||||||
|
clean-oras-cache:
|
||||||
|
desc: Remove all cache for oras commands
|
||||||
|
cmd: rm -rf {{ .ORAS_CACHE }}
|
||||||
|
|
||||||
|
clean-cache:
|
||||||
|
desc: Remove all image docker tar cache, images from the docker daemon, and ephemeral test fixtures
|
||||||
|
cmds:
|
||||||
|
- task: clean-docker-cache
|
||||||
|
- |
|
||||||
|
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
|
||||||
|
echo -e "${YELLOW}${BOLD}deleting ephemeral test fixtures in $dir${RESET}"
|
||||||
|
(make -C "$dir" clean)
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo -e "${BOLD}Deleted all ephemeral test fixtures${RESET}"
|
||||||
|
- rm -f {{ .LAST_CACHE_PULL_FILE }} {{ .CACHE_PATHS_FILE }}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ type backgroundLineReader struct {
|
|||||||
func (m *Handler) handleAttestationStarted(e partybus.Event) []tea.Model {
|
func (m *Handler) handleAttestationStarted(e partybus.Event) []tea.Model {
|
||||||
reader, prog, taskInfo, err := syftEventParsers.ParseAttestationStartedEvent(e)
|
reader, prog, taskInfo, err := syftEventParsers.ParseAttestationStartedEvent(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields("error", err).Warn("unable to parse event")
|
log.WithFields("error", err).Debug("unable to parse event")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ func (cts catalogerTaskModel) View() string {
|
|||||||
func (m *Handler) handleCatalogerTaskStarted(e partybus.Event) ([]tea.Model, tea.Cmd) {
|
func (m *Handler) handleCatalogerTaskStarted(e partybus.Event) ([]tea.Model, tea.Cmd) {
|
||||||
mon, info, err := syftEventParsers.ParseCatalogerTaskStarted(e)
|
mon, info, err := syftEventParsers.ParseCatalogerTaskStarted(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields("error", err).Warn("unable to parse event")
|
log.WithFields("error", err).Debug("unable to parse event")
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
func (m *Handler) handleFetchImage(e partybus.Event) []tea.Model {
|
func (m *Handler) handleFetchImage(e partybus.Event) []tea.Model {
|
||||||
imgName, prog, err := stereoEventParsers.ParseFetchImage(e)
|
imgName, prog, err := stereoEventParsers.ParseFetchImage(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields("error", err).Warn("unable to parse event")
|
log.WithFields("error", err).Debug("unable to parse event")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
func (m *Handler) handleFileIndexingStarted(e partybus.Event) []tea.Model {
|
func (m *Handler) handleFileIndexingStarted(e partybus.Event) []tea.Model {
|
||||||
path, prog, err := syftEventParsers.ParseFileIndexingStarted(e)
|
path, prog, err := syftEventParsers.ParseFileIndexingStarted(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields("error", err).Warn("unable to parse event")
|
log.WithFields("error", err).Debug("unable to parse event")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ type containerdPullStatusFormatter struct {
|
|||||||
func (m *Handler) handlePullContainerdImage(e partybus.Event) []tea.Model {
|
func (m *Handler) handlePullContainerdImage(e partybus.Event) []tea.Model {
|
||||||
_, pullStatus, err := stereoscopeParsers.ParsePullContainerdImage(e)
|
_, pullStatus, err := stereoscopeParsers.ParsePullContainerdImage(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields("error", err).Warn("unable to parse event")
|
log.WithFields("error", err).Debug("unable to parse event")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ type dockerPullStatusFormatter struct {
|
|||||||
func (m *Handler) handlePullDockerImage(e partybus.Event) []tea.Model {
|
func (m *Handler) handlePullDockerImage(e partybus.Event) []tea.Model {
|
||||||
_, pullStatus, err := stereoscopeParsers.ParsePullDockerImage(e)
|
_, pullStatus, err := stereoscopeParsers.ParsePullDockerImage(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields("error", err).Warn("unable to parse event")
|
log.WithFields("error", err).Debug("unable to parse event")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
func (m *Handler) handleReadImage(e partybus.Event) []tea.Model {
|
func (m *Handler) handleReadImage(e partybus.Event) []tea.Model {
|
||||||
imgMetadata, prog, err := stereoEventParsers.ParseReadImage(e)
|
imgMetadata, prog, err := stereoEventParsers.ParseReadImage(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields("error", err).Warn("unable to parse event")
|
log.WithFields("error", err).Debug("unable to parse event")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/anchore/clio"
|
"github.com/anchore/clio"
|
||||||
"github.com/anchore/stereoscope"
|
"github.com/anchore/stereoscope"
|
||||||
ui2 "github.com/anchore/syft/cmd/syft/cli/ui"
|
handler "github.com/anchore/syft/cmd/syft/cli/ui"
|
||||||
"github.com/anchore/syft/cmd/syft/internal/ui"
|
"github.com/anchore/syft/cmd/syft/internal/ui"
|
||||||
"github.com/anchore/syft/internal/bus"
|
"github.com/anchore/syft/internal/bus"
|
||||||
"github.com/anchore/syft/internal/log"
|
"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
|
WithConfigInRootHelp(). // --help on the root command renders the full application config in the help text
|
||||||
WithUIConstructor(
|
WithUIConstructor(
|
||||||
// select a UI based on the logging configuration and state of stdin (if stdin is a tty)
|
// select a UI based on the logging configuration and state of stdin (if stdin is a tty)
|
||||||
func(cfg clio.Config) ([]clio.UI, error) {
|
func(cfg clio.Config) (*clio.UICollection, error) {
|
||||||
noUI := ui.None(out, cfg.Log.Quiet)
|
noUI := ui.None(out, cfg.Log.Quiet)
|
||||||
if !cfg.Log.AllowUI(os.Stdin) || cfg.Log.Quiet {
|
if !cfg.Log.AllowUI(os.Stdin) || cfg.Log.Quiet {
|
||||||
return []clio.UI{noUI}, nil
|
return clio.NewUICollection(noUI), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return []clio.UI{
|
return clio.NewUICollection(
|
||||||
ui.New(out, cfg.Log.Quiet,
|
ui.New(out, cfg.Log.Quiet,
|
||||||
ui2.New(ui2.DefaultHandlerConfig()),
|
handler.New(handler.DefaultHandlerConfig()),
|
||||||
),
|
),
|
||||||
noUI,
|
noUI,
|
||||||
}, nil
|
), nil
|
||||||
},
|
},
|
||||||
).
|
).
|
||||||
WithInitializers(
|
WithInitializers(
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ type attestOptions struct {
|
|||||||
options.UpdateCheck `yaml:",inline" mapstructure:",squash"`
|
options.UpdateCheck `yaml:",inline" mapstructure:",squash"`
|
||||||
options.Catalog `yaml:",inline" mapstructure:",squash"`
|
options.Catalog `yaml:",inline" mapstructure:",squash"`
|
||||||
Attest options.Attest `yaml:"attest" mapstructure:"attest"`
|
Attest options.Attest `yaml:"attest" mapstructure:"attest"`
|
||||||
|
Cache options.Cache `json:"-" yaml:"cache" mapstructure:"cache"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Attest(app clio.Application) *cobra.Command {
|
func Attest(app clio.Application) *cobra.Command {
|
||||||
@@ -51,7 +52,7 @@ func Attest(app clio.Application) *cobra.Command {
|
|||||||
opts := defaultAttestOptions()
|
opts := defaultAttestOptions()
|
||||||
|
|
||||||
// template format explicitly not allowed
|
// template format explicitly not allowed
|
||||||
opts.Format.Template.Enabled = false
|
opts.Template.Enabled = false
|
||||||
|
|
||||||
return app.SetupCommand(&cobra.Command{
|
return app.SetupCommand(&cobra.Command{
|
||||||
Use: "attest --output [FORMAT] <IMAGE>",
|
Use: "attest --output [FORMAT] <IMAGE>",
|
||||||
@@ -77,6 +78,7 @@ func defaultAttestOptions() attestOptions {
|
|||||||
Output: defaultAttestOutputOptions(),
|
Output: defaultAttestOutputOptions(),
|
||||||
UpdateCheck: options.DefaultUpdateCheck(),
|
UpdateCheck: options.DefaultUpdateCheck(),
|
||||||
Catalog: options.DefaultCatalog(),
|
Catalog: options.DefaultCatalog(),
|
||||||
|
Cache: options.DefaultCache(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,14 +93,13 @@ func defaultAttestOutputOptions() options.Output {
|
|||||||
string(spdxtagvalue.ID),
|
string(spdxtagvalue.ID),
|
||||||
},
|
},
|
||||||
Outputs: []string{syftjson.ID.String()},
|
Outputs: []string{syftjson.ID.String()},
|
||||||
OutputFile: options.OutputFile{ // nolint:staticcheck
|
OutputFile: options.OutputFile{ //nolint:staticcheck
|
||||||
Enabled: false, // explicitly not allowed
|
Enabled: false, // explicitly not allowed
|
||||||
},
|
},
|
||||||
Format: options.DefaultFormat(),
|
Format: options.DefaultFormat(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:funlen
|
|
||||||
func runAttest(ctx context.Context, id clio.Identification, opts *attestOptions, userInput string) error {
|
func runAttest(ctx context.Context, id clio.Identification, opts *attestOptions, userInput string) error {
|
||||||
// TODO: what other validation here besides binary name?
|
// TODO: what other validation here besides binary name?
|
||||||
if !commandExists(cosignBinName) {
|
if !commandExists(cosignBinName) {
|
||||||
@@ -135,7 +136,7 @@ func writeSBOMToFormattedFile(s *sbom.SBOM, sbomFile io.Writer, opts *attestOpti
|
|||||||
return fmt.Errorf("no output file provided")
|
return fmt.Errorf("no output file provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
encs, err := opts.Format.Encoders()
|
encs, err := opts.Encoders()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create encoders: %w", err)
|
return fmt.Errorf("unable to create encoders: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package commands
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -12,9 +13,18 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/anchore/clio"
|
"github.com/anchore/clio"
|
||||||
|
"github.com/anchore/syft/cmd/syft/internal/options"
|
||||||
"github.com/anchore/syft/internal/bus"
|
"github.com/anchore/syft/internal/bus"
|
||||||
"github.com/anchore/syft/internal/task"
|
"github.com/anchore/syft/internal/task"
|
||||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
"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)
|
||||||
)
|
)
|
||||||
|
|
||||||
type catalogerListOptions struct {
|
type catalogerListOptions struct {
|
||||||
@@ -46,6 +56,7 @@ func CatalogerList(app clio.Application) *cobra.Command {
|
|||||||
return app.SetupCommand(&cobra.Command{
|
return app.SetupCommand(&cobra.Command{
|
||||||
Use: "list [OPTIONS]",
|
Use: "list [OPTIONS]",
|
||||||
Short: "List available catalogers",
|
Short: "List available catalogers",
|
||||||
|
PreRunE: disableUI(app, os.Stdout),
|
||||||
RunE: func(_ *cobra.Command, _ []string) error {
|
RunE: func(_ *cobra.Command, _ []string) error {
|
||||||
return runCatalogerList(opts)
|
return runCatalogerList(opts)
|
||||||
},
|
},
|
||||||
@@ -53,13 +64,19 @@ func CatalogerList(app clio.Application) *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runCatalogerList(opts *catalogerListOptions) error {
|
func runCatalogerList(opts *catalogerListOptions) error {
|
||||||
factories := task.DefaultPackageTaskFactories()
|
pkgTaskFactories := task.DefaultPackageTaskFactories()
|
||||||
allTasks, err := factories.Tasks(task.DefaultCatalogingFactoryConfig())
|
fileTaskFactories := task.DefaultFileTaskFactories()
|
||||||
|
allPkgTasks, err := pkgTaskFactories.Tasks(task.DefaultCatalogingFactoryConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create cataloger tasks: %w", err)
|
return fmt.Errorf("unable to create pkg cataloger tasks: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
report, err := catalogerListReport(opts, allTasks)
|
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})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to generate cataloger list report: %w", err)
|
return fmt.Errorf("unable to generate cataloger list report: %w", err)
|
||||||
}
|
}
|
||||||
@@ -69,11 +86,14 @@ func runCatalogerList(opts *catalogerListOptions) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func catalogerListReport(opts *catalogerListOptions, allTasks []task.Task) (string, error) {
|
func catalogerListReport(opts *catalogerListOptions, allTaskGroups [][]task.Task) (string, error) {
|
||||||
selectedTasks, selectionEvidence, err := task.Select(allTasks,
|
defaultCatalogers := options.Flatten(opts.DefaultCatalogers)
|
||||||
pkgcataloging.NewSelectionRequest().
|
selectCatalogers := options.Flatten(opts.SelectCatalogers)
|
||||||
WithDefaults(opts.DefaultCatalogers...).
|
selectedTaskGroups, selectionEvidence, err := task.SelectInGroups(
|
||||||
WithExpression(opts.SelectCatalogers...),
|
allTaskGroups,
|
||||||
|
cataloging.NewSelectionRequest().
|
||||||
|
WithDefaults(defaultCatalogers...).
|
||||||
|
WithExpression(selectCatalogers...),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("unable to select catalogers: %w", err)
|
return "", fmt.Errorf("unable to select catalogers: %w", err)
|
||||||
@@ -82,12 +102,12 @@ func catalogerListReport(opts *catalogerListOptions, allTasks []task.Task) (stri
|
|||||||
|
|
||||||
switch opts.Output {
|
switch opts.Output {
|
||||||
case "json":
|
case "json":
|
||||||
report, err = renderCatalogerListJSON(selectedTasks, selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
report, err = renderCatalogerListJSON(flattenTaskGroups(selectedTaskGroups), selectionEvidence, defaultCatalogers, selectCatalogers)
|
||||||
case "table", "":
|
case "table", "":
|
||||||
if opts.ShowHidden {
|
if opts.ShowHidden {
|
||||||
report = renderCatalogerListTable(allTasks, selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
report = renderCatalogerListTables(allTaskGroups, selectionEvidence)
|
||||||
} else {
|
} else {
|
||||||
report = renderCatalogerListTable(selectedTasks, selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
report = renderCatalogerListTables(selectedTaskGroups, selectionEvidence)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +118,14 @@ func catalogerListReport(opts *catalogerListOptions, allTasks []task.Task) (stri
|
|||||||
return report, nil
|
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) {
|
func renderCatalogerListJSON(tasks []task.Task, selection task.Selection, defaultSelections, selections []string) (string, error) {
|
||||||
type node struct {
|
type node struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -109,7 +137,12 @@ func renderCatalogerListJSON(tasks []task.Task, selection task.Selection, defaul
|
|||||||
nodesByName := make(map[string]node)
|
nodesByName := make(map[string]node)
|
||||||
|
|
||||||
for name := range tagsByName {
|
for name := range tagsByName {
|
||||||
tagsSelected := selection.TokensByTask[name].SelectedOn.List()
|
tokensByTask, ok := selection.TokensByTask[name]
|
||||||
|
|
||||||
|
var tagsSelected []string
|
||||||
|
if ok {
|
||||||
|
tagsSelected = tokensByTask.SelectedOn.List()
|
||||||
|
}
|
||||||
|
|
||||||
if len(tagsSelected) == 1 && tagsSelected[0] == "all" {
|
if len(tagsSelected) == 1 && tagsSelected[0] == "all" {
|
||||||
tagsSelected = tagsByName[name]
|
tagsSelected = tagsByName[name]
|
||||||
@@ -153,10 +186,56 @@ func renderCatalogerListJSON(tasks []task.Task, selection task.Selection, defaul
|
|||||||
return string(by), err
|
return string(by), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderCatalogerListTable(tasks []task.Task, selection task.Selection, defaultSelections, selections []string) string {
|
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)))
|
||||||
|
}
|
||||||
|
|
||||||
t := table.NewWriter()
|
t := table.NewWriter()
|
||||||
t.SetStyle(table.StyleLight)
|
t.SetStyle(table.StyleLight)
|
||||||
t.AppendHeader(table.Row{"Cataloger", "Tags"})
|
t.AppendHeader(table.Row{kindTitle, "Tags"})
|
||||||
|
|
||||||
names, tagsByName := extractTaskInfo(tasks)
|
names, tagsByName := extractTaskInfo(tasks)
|
||||||
|
|
||||||
@@ -172,27 +251,12 @@ func renderCatalogerListTable(tasks []task.Task, selection task.Selection, defau
|
|||||||
|
|
||||||
report := t.Render()
|
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
|
return report
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatRow(name string, tags []string, selection task.Selection) table.Row {
|
func formatRow(name string, tags []string, selection task.Selection) table.Row {
|
||||||
isIncluded := selection.Result.Has(name)
|
isIncluded := selection.Result.Has(name)
|
||||||
|
defaults := strset.New(selection.Request.DefaultNamesOrTags...)
|
||||||
var selections *task.TokenSelection
|
var selections *task.TokenSelection
|
||||||
if s, exists := selection.TokensByTask[name]; exists {
|
if s, exists := selection.TokensByTask[name]; exists {
|
||||||
selections = &s
|
selections = &s
|
||||||
@@ -200,35 +264,32 @@ func formatRow(name string, tags []string, selection task.Selection) table.Row {
|
|||||||
|
|
||||||
var formattedTags []string
|
var formattedTags []string
|
||||||
for _, tag := range tags {
|
for _, tag := range tags {
|
||||||
formattedTags = append(formattedTags, formatToken(tag, selections, isIncluded))
|
formattedTags = append(formattedTags, formatToken(tag, selections, isIncluded, defaults))
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagStr string
|
var tagStr string
|
||||||
if isIncluded {
|
if isIncluded {
|
||||||
tagStr = strings.Join(formattedTags, ", ")
|
tagStr = strings.Join(formattedTags, ", ")
|
||||||
} else {
|
} else {
|
||||||
tagStr = strings.Join(formattedTags, grey.Render(", "))
|
tagStr = strings.Join(formattedTags, deselectedStyle.Render(", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: selection should keep warnings (non-selections) in struct
|
// TODO: selection should keep warnings (non-selections) in struct
|
||||||
|
|
||||||
return table.Row{
|
return table.Row{
|
||||||
formatToken(name, selections, isIncluded),
|
formatToken(name, selections, isIncluded, defaults),
|
||||||
tagStr,
|
tagStr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
func formatToken(token string, selection *task.TokenSelection, included bool, defaults *strset.Set) string {
|
||||||
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 {
|
if included && selection != nil {
|
||||||
// format all tokens in selection in green
|
// format all tokens in selection in green
|
||||||
if selection.SelectedOn.Has(token) {
|
if selection.SelectedOn.Has(token) {
|
||||||
return green.Render(token)
|
if defaults.Has(token) {
|
||||||
|
return defaultStyle.Render(token)
|
||||||
|
}
|
||||||
|
return activelyAddedStyle.Render(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
return token
|
return token
|
||||||
@@ -236,10 +297,12 @@ func formatToken(token string, selection *task.TokenSelection, included bool) st
|
|||||||
|
|
||||||
// format all tokens in selection in red, all others in grey
|
// format all tokens in selection in red, all others in grey
|
||||||
if selection != nil && selection.DeselectedOn.Has(token) {
|
if selection != nil && selection.DeselectedOn.Has(token) {
|
||||||
return red.Render(token)
|
return activelyRemovedStyle.Render(token)
|
||||||
}
|
}
|
||||||
|
if defaults.Has(token) {
|
||||||
return grey.Render(token)
|
return deselectedDefaultStyle.Render(token)
|
||||||
|
}
|
||||||
|
return deselectedStyle.Render(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractTaskInfo(tasks []task.Task) ([]string, map[string][]string) {
|
func extractTaskInfo(tasks []task.Task) ([]string, map[string][]string) {
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ func (d dummyTask) Execute(_ context.Context, _ file.Resolver, _ sbomsync.Builde
|
|||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testTasks() []task.Task {
|
func testTasks() [][]task.Task {
|
||||||
return []task.Task{
|
return [][]task.Task{
|
||||||
|
{
|
||||||
dummyTask{
|
dummyTask{
|
||||||
name: "task1",
|
name: "task1",
|
||||||
selectors: []string{"image", "a", "b", "1"},
|
selectors: []string{"image", "a", "b", "1"},
|
||||||
@@ -58,6 +59,17 @@ func testTasks() []task.Task {
|
|||||||
name: "task4",
|
name: "task4",
|
||||||
selectors: []string{"directory", "d", "e", "4"},
|
selectors: []string{"directory", "d", "e", "4"},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dummyTask{
|
||||||
|
name: "file-task1",
|
||||||
|
selectors: []string{"file", "ft", "ft-1-b"},
|
||||||
|
},
|
||||||
|
dummyTask{
|
||||||
|
name: "file-task2",
|
||||||
|
selectors: []string{"file", "ft", "ft-2-b"},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,16 +88,23 @@ func Test_catalogerListReport(t *testing.T) {
|
|||||||
return c
|
return c
|
||||||
}(),
|
}(),
|
||||||
want: `
|
want: `
|
||||||
Default selections:
|
Default selections: 1
|
||||||
- "all"
|
• 'all'
|
||||||
┌───────────┬────────────────────┐
|
Selection expressions: 0
|
||||||
│ CATALOGER │ TAGS │
|
┌────────────────┬──────────────────┐
|
||||||
├───────────┼────────────────────┤
|
│ 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 │
|
│ task1 │ 1, a, b, image │
|
||||||
│ task2 │ 2, b, c, image │
|
│ task2 │ 2, b, c, image │
|
||||||
│ task3 │ 3, c, d, directory │
|
│ task3 │ 3, c, d, directory │
|
||||||
│ task4 │ 4, d, directory, e │
|
│ task4 │ 4, d, directory, e │
|
||||||
└───────────┴────────────────────┘
|
└───────────────────┴────────────────────┘
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -96,7 +115,7 @@ Default selections:
|
|||||||
return c
|
return c
|
||||||
}(),
|
}(),
|
||||||
want: `
|
want: `
|
||||||
{"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"]}]}
|
{"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"]}]}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -105,19 +124,27 @@ Default selections:
|
|||||||
c := defaultCatalogerListOptions()
|
c := defaultCatalogerListOptions()
|
||||||
c.Output = "table"
|
c.Output = "table"
|
||||||
c.DefaultCatalogers = []string{
|
c.DefaultCatalogers = []string{
|
||||||
"image",
|
"image", // note: for backwards compatibility file will automatically be added
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}(),
|
}(),
|
||||||
want: `
|
want: `
|
||||||
Default selections:
|
Default selections: 2
|
||||||
- "image"
|
• 'image'
|
||||||
┌───────────┬────────────────┐
|
• 'file'
|
||||||
│ CATALOGER │ TAGS │
|
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 │
|
│ task1 │ 1, a, b, image │
|
||||||
│ task2 │ 2, b, c, image │
|
│ task2 │ 2, b, c, image │
|
||||||
└───────────┴────────────────┘
|
└───────────────────┴────────────────┘
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -131,7 +158,7 @@ Default selections:
|
|||||||
return c
|
return c
|
||||||
}(),
|
}(),
|
||||||
want: `
|
want: `
|
||||||
{"default":["image"],"selection":[],"catalogers":[{"name":"task1","tags":["image"]},{"name":"task2","tags":["image"]}]}
|
{"default":["image"],"selection":[],"catalogers":[{"name":"file-task1","tags":["file"]},{"name":"file-task2","tags":["file"]},{"name":"task1","tags":["image"]},{"name":"task2","tags":["image"]}]}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -147,23 +174,69 @@ Default selections:
|
|||||||
"+task3",
|
"+task3",
|
||||||
"-c",
|
"-c",
|
||||||
"b",
|
"b",
|
||||||
|
"-file",
|
||||||
|
"+file-task1",
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}(),
|
}(),
|
||||||
want: `
|
want: `
|
||||||
Default selections:
|
Default selections: 1
|
||||||
- "image"
|
• 'image'
|
||||||
Selected by expressions:
|
Selection expressions: 6
|
||||||
- "-directory"
|
• 'b' (intersect)
|
||||||
- "+task3"
|
• '-c' (remove)
|
||||||
- "-c"
|
• '-directory' (remove)
|
||||||
- "b"
|
• '-file' (remove)
|
||||||
┌───────────┬────────────────────┐
|
• '+file-task1' (add)
|
||||||
│ CATALOGER │ TAGS │
|
• '+task3' (add)
|
||||||
├───────────┼────────────────────┤
|
┌────────────────┬──────────────────┐
|
||||||
|
│ FILE CATALOGER │ TAGS │
|
||||||
|
├────────────────┼──────────────────┤
|
||||||
|
│ file-task1 │ file, ft, ft-1-b │
|
||||||
|
└────────────────┴──────────────────┘
|
||||||
|
┌───────────────────┬────────────────────┐
|
||||||
|
│ PACKAGE CATALOGER │ TAGS │
|
||||||
|
├───────────────────┼────────────────────┤
|
||||||
│ task1 │ 1, a, b, image │
|
│ task1 │ 1, a, b, image │
|
||||||
│ task3 │ 3, c, d, directory │
|
│ 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 │
|
||||||
|
└───────────────────┴────────────────────┘
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -183,7 +256,7 @@ Selected by expressions:
|
|||||||
return c
|
return c
|
||||||
}(),
|
}(),
|
||||||
want: `
|
want: `
|
||||||
{"default":["image"],"selection":["-directory","+task3","-c","b"],"catalogers":[{"name":"task1","tags":["b","image"]},{"name":"task3","tags":["task3"]}]}
|
{"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"]}]}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
convertExample = ` {{.appName}} {{.command}} img.syft.json -o spdx-json convert a syft SBOM to spdx-json, output goes to stdout
|
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
|
{{.appName}} {{.command}} - -o spdx-json convert an SBOM from STDIN to spdx-json
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
@@ -28,7 +28,6 @@ type ConvertOptions struct {
|
|||||||
options.UpdateCheck `yaml:",inline" mapstructure:",squash"`
|
options.UpdateCheck `yaml:",inline" mapstructure:",squash"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:dupl
|
|
||||||
func Convert(app clio.Application) *cobra.Command {
|
func Convert(app clio.Application) *cobra.Command {
|
||||||
id := app.ID()
|
id := app.ID()
|
||||||
|
|
||||||
@@ -40,7 +39,7 @@ func Convert(app clio.Application) *cobra.Command {
|
|||||||
return app.SetupCommand(&cobra.Command{
|
return app.SetupCommand(&cobra.Command{
|
||||||
Use: "convert [SOURCE-SBOM] -o [FORMAT]",
|
Use: "convert [SOURCE-SBOM] -o [FORMAT]",
|
||||||
Short: "Convert between SBOM formats",
|
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#format-conversion-experimental",
|
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",
|
||||||
Example: internal.Tprintf(convertExample, map[string]interface{}{
|
Example: internal.Tprintf(convertExample, map[string]interface{}{
|
||||||
"appName": id.Name,
|
"appName": id.Name,
|
||||||
"command": "convert",
|
"command": "convert",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
"github.com/anchore/clio"
|
"github.com/anchore/clio"
|
||||||
|
"github.com/anchore/fangs"
|
||||||
"github.com/anchore/go-collections"
|
"github.com/anchore/go-collections"
|
||||||
"github.com/anchore/stereoscope"
|
"github.com/anchore/stereoscope"
|
||||||
"github.com/anchore/stereoscope/pkg/image"
|
"github.com/anchore/stereoscope/pkg/image"
|
||||||
@@ -68,6 +69,7 @@ type scanOptions struct {
|
|||||||
options.Output `yaml:",inline" mapstructure:",squash"`
|
options.Output `yaml:",inline" mapstructure:",squash"`
|
||||||
options.UpdateCheck `yaml:",inline" mapstructure:",squash"`
|
options.UpdateCheck `yaml:",inline" mapstructure:",squash"`
|
||||||
options.Catalog `yaml:",inline" mapstructure:",squash"`
|
options.Catalog `yaml:",inline" mapstructure:",squash"`
|
||||||
|
Cache options.Cache `json:"-" yaml:"cache" mapstructure:"cache"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultScanOptions() *scanOptions {
|
func defaultScanOptions() *scanOptions {
|
||||||
@@ -75,10 +77,10 @@ func defaultScanOptions() *scanOptions {
|
|||||||
Output: options.DefaultOutput(),
|
Output: options.DefaultOutput(),
|
||||||
UpdateCheck: options.DefaultUpdateCheck(),
|
UpdateCheck: options.DefaultUpdateCheck(),
|
||||||
Catalog: options.DefaultCatalog(),
|
Catalog: options.DefaultCatalog(),
|
||||||
|
Cache: options.DefaultCache(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:dupl
|
|
||||||
func Scan(app clio.Application) *cobra.Command {
|
func Scan(app clio.Application) *cobra.Command {
|
||||||
id := app.ID()
|
id := app.ID()
|
||||||
|
|
||||||
@@ -108,7 +110,7 @@ func (o *scanOptions) PostLoad() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *scanOptions) validateLegacyOptionsNotUsed() error {
|
func (o *scanOptions) validateLegacyOptionsNotUsed() error {
|
||||||
if o.Config.ConfigFile == "" {
|
if len(fangs.Flatten(o.ConfigFile)) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,14 +122,15 @@ func (o *scanOptions) validateLegacyOptionsNotUsed() error {
|
|||||||
File any `yaml:"file" json:"file" mapstructure:"file"`
|
File any `yaml:"file" json:"file" mapstructure:"file"`
|
||||||
}
|
}
|
||||||
|
|
||||||
by, err := os.ReadFile(o.Config.ConfigFile)
|
for _, f := range fangs.Flatten(o.ConfigFile) {
|
||||||
|
by, err := os.ReadFile(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to read config file during validations %q: %w", o.Config.ConfigFile, err)
|
return fmt.Errorf("unable to read config file during validations %q: %w", f, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var legacy legacyConfig
|
var legacy legacyConfig
|
||||||
if err := yaml.Unmarshal(by, &legacy); err != nil {
|
if err := yaml.Unmarshal(by, &legacy); err != nil {
|
||||||
return fmt.Errorf("unable to parse config file during validations %q: %w", o.Config.ConfigFile, err)
|
return fmt.Errorf("unable to parse config file during validations %q: %w", f, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if legacy.DefaultImagePullSource != nil {
|
if legacy.DefaultImagePullSource != nil {
|
||||||
@@ -145,7 +148,7 @@ func (o *scanOptions) validateLegacyOptionsNotUsed() error {
|
|||||||
if legacy.File != nil && reflect.TypeOf(legacy.File).Kind() == reflect.String {
|
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 fmt.Errorf("the config file option 'file' has been removed, please use 'outputs' instead")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,13 +156,13 @@ func validateScanArgs(cmd *cobra.Command, args []string) error {
|
|||||||
return validateArgs(cmd, args, "an image/directory argument is required")
|
return validateArgs(cmd, args, "an image/directory argument is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateArgs(cmd *cobra.Command, args []string, error string) error {
|
func validateArgs(cmd *cobra.Command, args []string, err string) error {
|
||||||
if len(args) == 0 {
|
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.
|
// 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 {
|
if err := cmd.Help(); err != nil {
|
||||||
return fmt.Errorf("unable to display help: %w", err)
|
return fmt.Errorf("unable to display help: %w", err)
|
||||||
}
|
}
|
||||||
return fmt.Errorf(error)
|
return fmt.Errorf("%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return cobra.MaximumNArgs(1)(cmd, args)
|
return cobra.MaximumNArgs(1)(cmd, args)
|
||||||
@@ -394,13 +397,13 @@ func getExplanation(expErr task.ErrInvalidExpression) string {
|
|||||||
|
|
||||||
if errors.Is(err, task.ErrNamesNotAllowed) {
|
if errors.Is(err, task.ErrNamesNotAllowed) {
|
||||||
if expErr.Operation == task.SubSelectOperation {
|
if expErr.Operation == task.SubSelectOperation {
|
||||||
return "However, " + err.Error() + ".\nIt seems like you are intending to add a cataloger in addition to the default set." // nolint:goconst
|
return "However, " + err.Error() + ".\nIt seems like you are intending to add a cataloger in addition to the default set."
|
||||||
}
|
}
|
||||||
return "However, " + err.Error() + "." // nolint:goconst
|
return "However, " + err.Error() + "."
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, task.ErrTagsNotAllowed) {
|
if errors.Is(err, task.ErrTagsNotAllowed) {
|
||||||
return "However, " + err.Error() + ".\nAdding groups of catalogers may result in surprising behavior (create inaccurate SBOMs)." // nolint:goconst
|
return "However, " + err.Error() + ".\nAdding groups of catalogers may result in surprising behavior (create inaccurate SBOMs)."
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, task.ErrAllNotAllowed) {
|
if errors.Is(err, task.ErrAllNotAllowed) {
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
package options
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/adrg/xdg"
|
||||||
|
|
||||||
|
"github.com/anchore/clio"
|
||||||
|
"github.com/anchore/go-homedir"
|
||||||
|
"github.com/anchore/syft/internal/cache"
|
||||||
|
"github.com/anchore/syft/internal/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cache provides configuration for the Syft caching behavior
|
||||||
|
type Cache struct {
|
||||||
|
Dir string `yaml:"dir" mapstructure:"dir"`
|
||||||
|
TTL string `yaml:"ttl" mapstructure:"ttl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cache) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||||
|
descriptions.Add(&c.Dir, "root directory to cache any downloaded content; empty string will use an in-memory cache")
|
||||||
|
descriptions.Add(&c.TTL, "time to live for cached data; setting this to 0 will disable caching entirely")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cache) PostLoad() error {
|
||||||
|
ttl, err := parseDuration(c.TTL)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("unable to parse duration '%v', using default (%s) due to: %v", c.TTL, durationToString(defaultTTL()), err)
|
||||||
|
ttl = defaultTTL()
|
||||||
|
}
|
||||||
|
// if TTL is <= 0, disable caching entirely
|
||||||
|
if ttl <= 0 {
|
||||||
|
cache.SetManager(nil)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// if dir == "" but we have a TTL, use an in-memory cache
|
||||||
|
if c.Dir == "" {
|
||||||
|
cache.SetManager(cache.NewInMemory(ttl))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
dir, err := homedir.Expand(c.Dir)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("unable to expand cache directory %s: %v", c.Dir, err)
|
||||||
|
cache.SetManager(cache.NewInMemory(ttl))
|
||||||
|
} else {
|
||||||
|
m, err := cache.NewFromDir(dir, ttl)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("unable to get filesystem cache at %s: %v", c.Dir, err)
|
||||||
|
cache.SetManager(cache.NewInMemory(ttl))
|
||||||
|
} else {
|
||||||
|
cache.SetManager(m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ interface {
|
||||||
|
clio.PostLoader
|
||||||
|
clio.FieldDescriber
|
||||||
|
} = (*Cache)(nil)
|
||||||
|
|
||||||
|
func DefaultCache() Cache {
|
||||||
|
return Cache{
|
||||||
|
Dir: defaultDir(),
|
||||||
|
TTL: durationToString(defaultTTL()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultTTL() time.Duration {
|
||||||
|
return 7 * 24 * time.Hour
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultDir() string {
|
||||||
|
var err error
|
||||||
|
cacheRoot := xdg.CacheHome
|
||||||
|
if cacheRoot == "" {
|
||||||
|
cacheRoot, err = homedir.Dir()
|
||||||
|
if err != nil {
|
||||||
|
cacheRoot = os.TempDir()
|
||||||
|
log.Debugf("unable to get stable cache directory due to: %v, defaulting cache to temp dir: %s", err, cacheRoot)
|
||||||
|
} else {
|
||||||
|
cacheRoot = filepath.Join(cacheRoot, ".cache")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Join(cacheRoot, "syft")
|
||||||
|
}
|
||||||
|
|
||||||
|
func durationToString(duration time.Duration) string {
|
||||||
|
days := int64(duration / (24 * time.Hour))
|
||||||
|
remain := duration % (24 * time.Hour)
|
||||||
|
out := ""
|
||||||
|
if days > 0 {
|
||||||
|
out = fmt.Sprintf("%vd", days)
|
||||||
|
}
|
||||||
|
if remain != 0 {
|
||||||
|
out += remain.String()
|
||||||
|
}
|
||||||
|
if out == "" {
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDuration(duration string) (time.Duration, error) {
|
||||||
|
whitespace := regexp.MustCompile(`\s+`)
|
||||||
|
duration = strings.ToLower(whitespace.ReplaceAllString(duration, ""))
|
||||||
|
parts := strings.SplitN(duration, "d", 2)
|
||||||
|
var days time.Duration
|
||||||
|
var remain time.Duration
|
||||||
|
var err error
|
||||||
|
if len(parts) > 1 {
|
||||||
|
numDays, daysErr := strconv.Atoi(parts[0])
|
||||||
|
if daysErr != nil {
|
||||||
|
return 0, daysErr
|
||||||
|
}
|
||||||
|
days = time.Duration(numDays) * 24 * time.Hour
|
||||||
|
if len(parts[1]) > 0 {
|
||||||
|
remain, err = time.ParseDuration(parts[1])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
remain, err = time.ParseDuration(duration)
|
||||||
|
}
|
||||||
|
return days + remain, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,323 @@
|
|||||||
|
package options
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/adrg/xdg"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/anchore/go-homedir"
|
||||||
|
"github.com/anchore/syft/internal"
|
||||||
|
"github.com/anchore/syft/internal/cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_defaultDir(t *testing.T) {
|
||||||
|
tmpDir := filepath.Join(t.TempDir(), "cache-temp")
|
||||||
|
xdgCacheDir := filepath.Join(tmpDir, "fake-xdg-cache")
|
||||||
|
homeDir := filepath.Join(tmpDir, "fake-home")
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
env map[string]string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no-xdg",
|
||||||
|
env: map[string]string{
|
||||||
|
"HOME": homeDir,
|
||||||
|
},
|
||||||
|
expected: homeDir,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "xdg-cache",
|
||||||
|
env: map[string]string{
|
||||||
|
"XDG_CACHE_HOME": xdgCacheDir,
|
||||||
|
},
|
||||||
|
expected: xdgCacheDir,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// capture all the initial environment variables to reset them before we reset library caches
|
||||||
|
env := map[string]string{
|
||||||
|
"HOME": "",
|
||||||
|
"XDG_DATA_HOME": "",
|
||||||
|
"XDG_DATA_DIRS": "",
|
||||||
|
"XDG_CONFIG_HOME": "",
|
||||||
|
"XDG_CONFIG_DIRS": "",
|
||||||
|
"XDG_STATE_HOME": "",
|
||||||
|
"XDG_CACHE_HOME": "",
|
||||||
|
"XDG_RUNTIME_DIR": "",
|
||||||
|
}
|
||||||
|
for k := range env {
|
||||||
|
env[k] = os.Getenv(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
restoreCache(t)
|
||||||
|
|
||||||
|
for k, v := range test.env {
|
||||||
|
patchEnv(t, k, v)
|
||||||
|
}
|
||||||
|
xdg.Reload()
|
||||||
|
|
||||||
|
got := defaultDir()
|
||||||
|
|
||||||
|
require.True(t, strings.HasPrefix(got, test.expected))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_cacheOptions(t *testing.T) {
|
||||||
|
tmp := t.TempDir()
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
opts Cache
|
||||||
|
test func(t *testing.T)
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "disable-1",
|
||||||
|
opts: Cache{
|
||||||
|
Dir: "some-dir",
|
||||||
|
TTL: "0",
|
||||||
|
},
|
||||||
|
test: func(t *testing.T) {
|
||||||
|
c := cache.GetManager().GetCache("test-disable-1", "v-disable-1")
|
||||||
|
err := c.Write("key-disable-1", strings.NewReader("some-value-disable-1"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
rdr, err := c.Read("key-disable-1")
|
||||||
|
require.Nil(t, rdr)
|
||||||
|
require.Error(t, err)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "disable-2",
|
||||||
|
opts: Cache{
|
||||||
|
Dir: "some-dir",
|
||||||
|
TTL: "0s",
|
||||||
|
},
|
||||||
|
test: func(t *testing.T) {
|
||||||
|
c := cache.GetManager().GetCache("test-disable-2", "v-disable-2")
|
||||||
|
err := c.Write("key-disable-2", strings.NewReader("some-value-disable-2"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
rdr, err := c.Read("key-disable-2")
|
||||||
|
require.Nil(t, rdr)
|
||||||
|
require.Error(t, err)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "disable-3",
|
||||||
|
opts: Cache{
|
||||||
|
Dir: "some-dir",
|
||||||
|
TTL: "0d",
|
||||||
|
},
|
||||||
|
test: func(t *testing.T) {
|
||||||
|
c := cache.GetManager().GetCache("test-disable-3", "v-disable-3")
|
||||||
|
err := c.Write("key-disable-3", strings.NewReader("some-value-disable-3"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
rdr, err := c.Read("key-disable-3")
|
||||||
|
require.Nil(t, rdr)
|
||||||
|
require.Error(t, err)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "in-memory",
|
||||||
|
opts: Cache{
|
||||||
|
Dir: "",
|
||||||
|
TTL: "10m",
|
||||||
|
},
|
||||||
|
test: func(t *testing.T) {
|
||||||
|
c := cache.GetManager().GetCache("test-mem", "v-mem")
|
||||||
|
err := c.Write("key-mem", strings.NewReader("some-value-mem"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
rdr, err := c.Read("key-mem")
|
||||||
|
require.NotNil(t, rdr)
|
||||||
|
defer internal.CloseAndLogError(rdr, "")
|
||||||
|
require.NoError(t, err)
|
||||||
|
data, err := io.ReadAll(rdr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "some-value-mem", string(data))
|
||||||
|
require.NoDirExists(t, filepath.Join("test-mem", "v-mem"))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "on disk",
|
||||||
|
opts: Cache{
|
||||||
|
Dir: tmp,
|
||||||
|
TTL: "10m",
|
||||||
|
},
|
||||||
|
test: func(t *testing.T) {
|
||||||
|
c := cache.GetManager().GetCache("test-disk", "v-disk")
|
||||||
|
err := c.Write("key-disk", strings.NewReader("some-value-disk"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
rdr, err := c.Read("key-disk")
|
||||||
|
require.NotNil(t, rdr)
|
||||||
|
defer internal.CloseAndLogError(rdr, "")
|
||||||
|
require.NoError(t, err)
|
||||||
|
data, err := io.ReadAll(rdr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "some-value-disk", string(data))
|
||||||
|
require.DirExists(t, filepath.Join(tmp, "test-disk", "v-disk"))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
original := cache.GetManager()
|
||||||
|
defer cache.SetManager(original)
|
||||||
|
|
||||||
|
err := test.opts.PostLoad()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
test.test(t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_parseDuration(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
duration string
|
||||||
|
expect time.Duration
|
||||||
|
err require.ErrorAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
duration: "0d",
|
||||||
|
expect: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: "0m",
|
||||||
|
expect: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: "0s",
|
||||||
|
expect: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: "0",
|
||||||
|
expect: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: "1d",
|
||||||
|
expect: 24 * time.Hour,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: "7d",
|
||||||
|
expect: 7 * 24 * time.Hour,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: "365D",
|
||||||
|
expect: 365 * 24 * time.Hour,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: "7d1h1m1s",
|
||||||
|
expect: 7*24*time.Hour + time.Hour + time.Minute + time.Second,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: "7d 1h 1m 1s",
|
||||||
|
expect: 7*24*time.Hour + time.Hour + time.Minute + time.Second,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: "2h",
|
||||||
|
expect: 2 * time.Hour,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: "2h5m",
|
||||||
|
expect: 2*time.Hour + 5*time.Minute,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: "2h 5m",
|
||||||
|
expect: 2*time.Hour + 5*time.Minute,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: "d24h",
|
||||||
|
err: require.Error,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.duration, func(t *testing.T) {
|
||||||
|
got, err := parseDuration(test.duration)
|
||||||
|
if test.err != nil {
|
||||||
|
test.err(t, err)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
require.Equal(t, test.expect, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_durationToString(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
duration time.Duration
|
||||||
|
expect string
|
||||||
|
err require.ErrorAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
expect: "1d",
|
||||||
|
duration: 24 * time.Hour,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expect: "7d",
|
||||||
|
duration: 7 * 24 * time.Hour,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expect: "7d1h1m1s",
|
||||||
|
duration: 7*24*time.Hour + time.Hour + time.Minute + time.Second,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expect: "2h0m0s",
|
||||||
|
duration: 2 * time.Hour,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expect: "2h5m0s",
|
||||||
|
duration: 2*time.Hour + 5*time.Minute,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.expect, func(t *testing.T) {
|
||||||
|
got := durationToString(test.duration)
|
||||||
|
require.Equal(t, test.expect, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/anchore/fangs"
|
"github.com/anchore/fangs"
|
||||||
intFile "github.com/anchore/syft/internal/file"
|
intFile "github.com/anchore/syft/internal/file"
|
||||||
"github.com/anchore/syft/internal/log"
|
"github.com/anchore/syft/internal/log"
|
||||||
|
"github.com/anchore/syft/internal/task"
|
||||||
"github.com/anchore/syft/syft"
|
"github.com/anchore/syft/syft"
|
||||||
"github.com/anchore/syft/syft/cataloging"
|
"github.com/anchore/syft/syft/cataloging"
|
||||||
"github.com/anchore/syft/syft/cataloging/filecataloging"
|
"github.com/anchore/syft/syft/cataloging/filecataloging"
|
||||||
@@ -18,10 +19,12 @@ import (
|
|||||||
"github.com/anchore/syft/syft/file/cataloger/executable"
|
"github.com/anchore/syft/syft/file/cataloger/executable"
|
||||||
"github.com/anchore/syft/syft/file/cataloger/filecontent"
|
"github.com/anchore/syft/syft/file/cataloger/filecontent"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/binary"
|
"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/golang"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
|
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/kernel"
|
"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/pkg/cataloger/python"
|
||||||
"github.com/anchore/syft/syft/source"
|
"github.com/anchore/syft/syft/source"
|
||||||
)
|
)
|
||||||
@@ -32,16 +35,21 @@ type Catalog struct {
|
|||||||
DefaultCatalogers []string `yaml:"default-catalogers" json:"default-catalogers" mapstructure:"default-catalogers"`
|
DefaultCatalogers []string `yaml:"default-catalogers" json:"default-catalogers" mapstructure:"default-catalogers"`
|
||||||
SelectCatalogers []string `yaml:"select-catalogers" json:"select-catalogers" mapstructure:"select-catalogers"`
|
SelectCatalogers []string `yaml:"select-catalogers" json:"select-catalogers" mapstructure:"select-catalogers"`
|
||||||
Package packageConfig `yaml:"package" json:"package" mapstructure:"package"`
|
Package packageConfig `yaml:"package" json:"package" mapstructure:"package"`
|
||||||
|
License licenseConfig `yaml:"license" json:"license" mapstructure:"license"`
|
||||||
File fileConfig `yaml:"file" json:"file" mapstructure:"file"`
|
File fileConfig `yaml:"file" json:"file" mapstructure:"file"`
|
||||||
Scope string `yaml:"scope" json:"scope" mapstructure:"scope"`
|
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
|
Parallelism int `yaml:"parallelism" json:"parallelism" mapstructure:"parallelism"` // the number of catalog workers to run in parallel
|
||||||
Relationships relationshipsConfig `yaml:"relationships" json:"relationships" mapstructure:"relationships"`
|
Relationships relationshipsConfig `yaml:"relationships" json:"relationships" mapstructure:"relationships"`
|
||||||
|
Compliance complianceConfig `yaml:"compliance" json:"compliance" mapstructure:"compliance"`
|
||||||
|
Enrich []string `yaml:"enrich" json:"enrich" mapstructure:"enrich"`
|
||||||
|
|
||||||
// ecosystem-specific cataloger configuration
|
// ecosystem-specific cataloger configuration
|
||||||
|
Dotnet dotnetConfig `yaml:"dotnet" json:"dotnet" mapstructure:"dotnet"`
|
||||||
Golang golangConfig `yaml:"golang" json:"golang" mapstructure:"golang"`
|
Golang golangConfig `yaml:"golang" json:"golang" mapstructure:"golang"`
|
||||||
Java javaConfig `yaml:"java" json:"java" mapstructure:"java"`
|
Java javaConfig `yaml:"java" json:"java" mapstructure:"java"`
|
||||||
JavaScript javaScriptConfig `yaml:"javascript" json:"javascript" mapstructure:"javascript"`
|
JavaScript javaScriptConfig `yaml:"javascript" json:"javascript" mapstructure:"javascript"`
|
||||||
LinuxKernel linuxKernelConfig `yaml:"linux-kernel" json:"linux-kernel" mapstructure:"linux-kernel"`
|
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"`
|
Python pythonConfig `yaml:"python" json:"python" mapstructure:"python"`
|
||||||
|
|
||||||
// configuration for the source (the subject being analyzed)
|
// configuration for the source (the subject being analyzed)
|
||||||
@@ -50,24 +58,34 @@ type Catalog struct {
|
|||||||
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"`
|
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"`
|
||||||
Source sourceConfig `yaml:"source" json:"source" mapstructure:"source"`
|
Source sourceConfig `yaml:"source" json:"source" mapstructure:"source"`
|
||||||
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
|
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
|
||||||
|
|
||||||
|
// configuration for inclusion of unknown information within elements
|
||||||
|
Unknowns unknownsConfig `yaml:"unknowns" mapstructure:"unknowns"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ interface {
|
var _ interface {
|
||||||
clio.FlagAdder
|
clio.FlagAdder
|
||||||
clio.PostLoader
|
clio.PostLoader
|
||||||
fangs.FieldDescriber
|
clio.FieldDescriber
|
||||||
} = (*Catalog)(nil)
|
} = (*Catalog)(nil)
|
||||||
|
|
||||||
func DefaultCatalog() Catalog {
|
func DefaultCatalog() Catalog {
|
||||||
|
cfg := syft.DefaultCreateSBOMConfig()
|
||||||
return Catalog{
|
return Catalog{
|
||||||
|
Compliance: defaultComplianceConfig(),
|
||||||
Scope: source.SquashedScope.String(),
|
Scope: source.SquashedScope.String(),
|
||||||
Package: defaultPackageConfig(),
|
Package: defaultPackageConfig(),
|
||||||
|
License: defaultLicenseConfig(),
|
||||||
LinuxKernel: defaultLinuxKernelConfig(),
|
LinuxKernel: defaultLinuxKernelConfig(),
|
||||||
|
Nix: defaultNixConfig(),
|
||||||
|
Dotnet: defaultDotnetConfig(),
|
||||||
Golang: defaultGolangConfig(),
|
Golang: defaultGolangConfig(),
|
||||||
|
Java: defaultJavaConfig(),
|
||||||
File: defaultFileConfig(),
|
File: defaultFileConfig(),
|
||||||
Relationships: defaultRelationshipsConfig(),
|
Relationships: defaultRelationshipsConfig(),
|
||||||
|
Unknowns: defaultUnknowns(),
|
||||||
Source: defaultSourceConfig(),
|
Source: defaultSourceConfig(),
|
||||||
Parallelism: 1,
|
Parallelism: cfg.Parallelism,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,11 +94,14 @@ func (cfg Catalog) ToSBOMConfig(id clio.Identification) *syft.CreateSBOMConfig {
|
|||||||
WithTool(id.Name, id.Version).
|
WithTool(id.Name, id.Version).
|
||||||
WithParallelism(cfg.Parallelism).
|
WithParallelism(cfg.Parallelism).
|
||||||
WithRelationshipsConfig(cfg.ToRelationshipsConfig()).
|
WithRelationshipsConfig(cfg.ToRelationshipsConfig()).
|
||||||
|
WithComplianceConfig(cfg.ToComplianceConfig()).
|
||||||
|
WithUnknownsConfig(cfg.ToUnknownsConfig()).
|
||||||
WithSearchConfig(cfg.ToSearchConfig()).
|
WithSearchConfig(cfg.ToSearchConfig()).
|
||||||
WithPackagesConfig(cfg.ToPackagesConfig()).
|
WithPackagesConfig(cfg.ToPackagesConfig()).
|
||||||
|
WithLicenseConfig(cfg.ToLicenseConfig()).
|
||||||
WithFilesConfig(cfg.ToFilesConfig()).
|
WithFilesConfig(cfg.ToFilesConfig()).
|
||||||
WithCatalogerSelection(
|
WithCatalogerSelection(
|
||||||
pkgcataloging.NewSelectionRequest().
|
cataloging.NewSelectionRequest().
|
||||||
WithDefaults(cfg.DefaultCatalogers...).
|
WithDefaults(cfg.DefaultCatalogers...).
|
||||||
WithExpression(cfg.SelectCatalogers...),
|
WithExpression(cfg.SelectCatalogers...),
|
||||||
)
|
)
|
||||||
@@ -101,6 +122,20 @@ func (cfg Catalog) ToRelationshipsConfig() cataloging.RelationshipsConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cfg Catalog) ToComplianceConfig() cataloging.ComplianceConfig {
|
||||||
|
return cataloging.ComplianceConfig{
|
||||||
|
MissingName: cfg.Compliance.MissingName,
|
||||||
|
MissingVersion: cfg.Compliance.MissingVersion,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cfg Catalog) ToUnknownsConfig() cataloging.UnknownsConfig {
|
||||||
|
return cataloging.UnknownsConfig{
|
||||||
|
IncludeExecutablesWithoutPackages: cfg.Unknowns.ExecutablesWithoutPackages,
|
||||||
|
IncludeUnexpandedArchives: cfg.Unknowns.UnexpandedArchives,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (cfg Catalog) ToFilesConfig() filecataloging.Config {
|
func (cfg Catalog) ToFilesConfig() filecataloging.Config {
|
||||||
hashers, err := intFile.Hashers(cfg.File.Metadata.Digests...)
|
hashers, err := intFile.Hashers(cfg.File.Metadata.Digests...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -121,6 +156,13 @@ 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 {
|
func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
||||||
archiveSearch := cataloging.ArchiveSearchConfig{
|
archiveSearch := cataloging.ArchiveSearchConfig{
|
||||||
IncludeIndexedArchives: cfg.Package.SearchIndexedArchives,
|
IncludeIndexedArchives: cfg.Package.SearchIndexedArchives,
|
||||||
@@ -128,10 +170,17 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
|||||||
}
|
}
|
||||||
return pkgcataloging.Config{
|
return pkgcataloging.Config{
|
||||||
Binary: binary.DefaultClassifierCatalogerConfig(),
|
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().
|
Golang: golang.DefaultCatalogerConfig().
|
||||||
WithSearchLocalModCacheLicenses(cfg.Golang.SearchLocalModCacheLicenses).
|
WithSearchLocalModCacheLicenses(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Go, task.Golang), cfg.Golang.SearchLocalModCacheLicenses)).
|
||||||
WithLocalModCacheDir(cfg.Golang.LocalModCacheDir).
|
WithLocalModCacheDir(cfg.Golang.LocalModCacheDir).
|
||||||
WithSearchRemoteLicenses(cfg.Golang.SearchRemoteLicenses).
|
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).
|
WithProxy(cfg.Golang.Proxy).
|
||||||
WithNoProxy(cfg.Golang.NoProxy).
|
WithNoProxy(cfg.Golang.NoProxy).
|
||||||
WithMainModuleVersion(
|
WithMainModuleVersion(
|
||||||
@@ -141,18 +190,24 @@ func (cfg Catalog) ToPackagesConfig() pkgcataloging.Config {
|
|||||||
WithFromLDFlags(cfg.Golang.MainModuleVersion.FromLDFlags),
|
WithFromLDFlags(cfg.Golang.MainModuleVersion.FromLDFlags),
|
||||||
),
|
),
|
||||||
JavaScript: javascript.DefaultCatalogerConfig().
|
JavaScript: javascript.DefaultCatalogerConfig().
|
||||||
WithSearchRemoteLicenses(cfg.JavaScript.SearchRemoteLicenses).
|
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),
|
WithNpmBaseURL(cfg.JavaScript.NpmBaseURL),
|
||||||
LinuxKernel: kernel.LinuxKernelCatalogerConfig{
|
LinuxKernel: kernel.LinuxKernelCatalogerConfig{
|
||||||
CatalogModules: cfg.LinuxKernel.CatalogModules,
|
CatalogModules: cfg.LinuxKernel.CatalogModules,
|
||||||
},
|
},
|
||||||
|
Nix: nix.DefaultConfig().
|
||||||
|
WithCaptureOwnedFiles(cfg.Nix.CaptureOwnedFiles),
|
||||||
Python: python.CatalogerConfig{
|
Python: python.CatalogerConfig{
|
||||||
GuessUnpinnedRequirements: cfg.Python.GuessUnpinnedRequirements,
|
GuessUnpinnedRequirements: cfg.Python.GuessUnpinnedRequirements,
|
||||||
},
|
},
|
||||||
JavaArchive: java.DefaultArchiveCatalogerConfig().
|
JavaArchive: java.DefaultArchiveCatalogerConfig().
|
||||||
WithUseNetwork(cfg.Java.UseNetwork).
|
WithUseMavenLocalRepository(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Java, task.Maven), cfg.Java.UseMavenLocalRepository)).
|
||||||
|
WithMavenLocalRepositoryDir(cfg.Java.MavenLocalRepositoryDir).
|
||||||
|
WithUseNetwork(*multiLevelOption(false, enrichmentEnabled(cfg.Enrich, task.Java, task.Maven), cfg.Java.UseNetwork)).
|
||||||
WithMavenBaseURL(cfg.Java.MavenURL).
|
WithMavenBaseURL(cfg.Java.MavenURL).
|
||||||
WithArchiveTraversal(archiveSearch, cfg.Java.MaxParentRecursiveDepth),
|
WithArchiveTraversal(archiveSearch, cfg.Java.MaxParentRecursiveDepth).
|
||||||
|
WithResolveTransitiveDependencies(cfg.Java.ResolveTransitiveDependencies),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,6 +231,9 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
|
|||||||
flags.StringArrayVarP(&cfg.Catalogers, "catalogers", "",
|
flags.StringArrayVarP(&cfg.Catalogers, "catalogers", "",
|
||||||
"enable one or more package 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 pfp, ok := flags.(fangs.PFlagSetProvider); ok {
|
||||||
if err := pfp.PFlagSet().MarkDeprecated("catalogers", "use: override-default-catalogers and select-catalogers"); err != nil {
|
if err := pfp.PFlagSet().MarkDeprecated("catalogers", "use: override-default-catalogers and select-catalogers"); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -190,6 +248,9 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
|
|||||||
flags.StringArrayVarP(&cfg.SelectCatalogers, "select-catalogers", "",
|
flags.StringArrayVarP(&cfg.SelectCatalogers, "select-catalogers", "",
|
||||||
"add, remove, and filter the catalogers to be used")
|
"add, remove, and filter the catalogers to be used")
|
||||||
|
|
||||||
|
flags.StringArrayVarP(&cfg.Enrich, "enrich", "",
|
||||||
|
fmt.Sprintf("enable package data enrichment from local and online sources (options: %s)", strings.Join(publicisedEnrichmentOptions, ", ")))
|
||||||
|
|
||||||
flags.StringVarP(&cfg.Source.Name, "source-name", "",
|
flags.StringVarP(&cfg.Source.Name, "source-name", "",
|
||||||
"set the name of the target being analyzed")
|
"set the name of the target being analyzed")
|
||||||
|
|
||||||
@@ -201,7 +262,12 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *Catalog) DescribeFields(descriptions fangs.FieldDescriptionSet) {
|
func (cfg *Catalog) DescribeFields(descriptions fangs.FieldDescriptionSet) {
|
||||||
descriptions.Add(&cfg.Parallelism, "number of cataloger workers to run in parallel")
|
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.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.
|
||||||
|
Available options are: %s`, strings.Join(publicisedEnrichmentOptions, ", ")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *Catalog) PostLoad() error {
|
func (cfg *Catalog) PostLoad() error {
|
||||||
@@ -212,23 +278,12 @@ func (cfg *Catalog) PostLoad() error {
|
|||||||
return fmt.Errorf("cannot use both 'catalogers' and 'select-catalogers'/'default-catalogers' flags")
|
return fmt.Errorf("cannot use both 'catalogers' and 'select-catalogers'/'default-catalogers' flags")
|
||||||
}
|
}
|
||||||
|
|
||||||
flatten := func(l []string) []string {
|
cfg.From = Flatten(cfg.From)
|
||||||
var out []string
|
|
||||||
for _, v := range l {
|
|
||||||
for _, s := range strings.Split(v, ",") {
|
|
||||||
out = append(out, strings.TrimSpace(s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Strings(out)
|
|
||||||
|
|
||||||
return out
|
cfg.Catalogers = Flatten(cfg.Catalogers)
|
||||||
}
|
cfg.DefaultCatalogers = Flatten(cfg.DefaultCatalogers)
|
||||||
|
cfg.SelectCatalogers = Flatten(cfg.SelectCatalogers)
|
||||||
cfg.From = flatten(cfg.From)
|
cfg.Enrich = Flatten(cfg.Enrich)
|
||||||
|
|
||||||
cfg.Catalogers = flatten(cfg.Catalogers)
|
|
||||||
cfg.DefaultCatalogers = flatten(cfg.DefaultCatalogers)
|
|
||||||
cfg.SelectCatalogers = flatten(cfg.SelectCatalogers)
|
|
||||||
|
|
||||||
// for backwards compatibility
|
// for backwards compatibility
|
||||||
cfg.DefaultCatalogers = append(cfg.DefaultCatalogers, cfg.Catalogers...)
|
cfg.DefaultCatalogers = append(cfg.DefaultCatalogers, cfg.Catalogers...)
|
||||||
@@ -238,5 +293,75 @@ func (cfg *Catalog) PostLoad() error {
|
|||||||
return fmt.Errorf("bad scope value %q", cfg.Scope)
|
return fmt.Errorf("bad scope value %q", cfg.Scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the binary package exclusion code depends on the file overlap relationships being created upstream in processing
|
||||||
|
if !cfg.Relationships.PackageFileOwnershipOverlap && cfg.Package.ExcludeBinaryOverlapByOwnership {
|
||||||
|
return fmt.Errorf("cannot enable exclude-binary-overlap-by-ownership without enabling package-file-ownership-overlap")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Flatten(commaSeparatedEntries []string) []string {
|
||||||
|
var out []string
|
||||||
|
for _, v := range commaSeparatedEntries {
|
||||||
|
for _, s := range strings.Split(v, ",") {
|
||||||
|
out = append(out, strings.TrimSpace(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
var publicisedEnrichmentOptions = []string{
|
||||||
|
"all",
|
||||||
|
task.Golang,
|
||||||
|
task.Java,
|
||||||
|
task.JavaScript,
|
||||||
|
}
|
||||||
|
|
||||||
|
func enrichmentEnabled(enrichDirectives []string, features ...string) *bool {
|
||||||
|
if len(enrichDirectives) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled := func(features ...string) *bool {
|
||||||
|
for _, directive := range enrichDirectives {
|
||||||
|
enable := true
|
||||||
|
directive = strings.TrimPrefix(directive, "+") // +java and java are equivalent
|
||||||
|
if strings.HasPrefix(directive, "-") {
|
||||||
|
directive = directive[1:]
|
||||||
|
enable = false
|
||||||
|
}
|
||||||
|
for _, feature := range features {
|
||||||
|
if directive == feature {
|
||||||
|
return &enable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
enableAll := enabled("all")
|
||||||
|
disableAll := enabled("none")
|
||||||
|
|
||||||
|
if disableAll != nil && *disableAll {
|
||||||
|
if enableAll != nil {
|
||||||
|
log.Warn("you have specified to both enable and disable all enrichment functionality, defaulting to disabled")
|
||||||
|
}
|
||||||
|
enableAll = ptr(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for explicit enable/disable of feature names
|
||||||
|
for _, feat := range features {
|
||||||
|
enableFeature := enabled(feat)
|
||||||
|
if enableFeature != nil {
|
||||||
|
return enableFeature
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enableAll
|
||||||
|
}
|
||||||
|
|
||||||
|
func ptr[T any](val T) *T {
|
||||||
|
return &val
|
||||||
|
}
|
||||||
|
|||||||
@@ -57,6 +57,14 @@ func TestCatalog_PostLoad(t *testing.T) {
|
|||||||
assert.Empty(t, options.Catalogers)
|
assert.Empty(t, options.Catalogers)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "must have package overlap flag when pruning binaries by overlap",
|
||||||
|
options: Catalog{
|
||||||
|
Package: packageConfig{ExcludeBinaryOverlapByOwnership: true},
|
||||||
|
Relationships: relationshipsConfig{PackageFileOwnershipOverlap: false},
|
||||||
|
},
|
||||||
|
wantErr: assert.Error,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
@@ -70,3 +78,69 @@ func TestCatalog_PostLoad(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_enrichmentEnabled(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
directives string
|
||||||
|
test string
|
||||||
|
expected *bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
directives: "",
|
||||||
|
test: "java",
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directives: "none",
|
||||||
|
test: "java",
|
||||||
|
expected: ptr(false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directives: "none,+java",
|
||||||
|
test: "java",
|
||||||
|
expected: ptr(true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directives: "all,none",
|
||||||
|
test: "java",
|
||||||
|
expected: ptr(false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directives: "all",
|
||||||
|
test: "java",
|
||||||
|
expected: ptr(true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directives: "golang,js",
|
||||||
|
test: "java",
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directives: "golang,-js,java",
|
||||||
|
test: "java",
|
||||||
|
expected: ptr(true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directives: "golang,js,-java",
|
||||||
|
test: "java",
|
||||||
|
expected: ptr(false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directives: "all",
|
||||||
|
test: "java",
|
||||||
|
expected: ptr(true),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
directives: "all,-java",
|
||||||
|
test: "java",
|
||||||
|
expected: ptr(false),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.directives, func(t *testing.T) {
|
||||||
|
got := enrichmentEnabled(Flatten([]string{test.directives}), test.test)
|
||||||
|
assert.Equal(t, test.expected, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package options
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/anchore/fangs"
|
||||||
|
"github.com/anchore/syft/syft/cataloging"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ fangs.FieldDescriber = (*complianceConfig)(nil)
|
||||||
|
_ fangs.PostLoader = (*complianceConfig)(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
type complianceConfig struct {
|
||||||
|
MissingName cataloging.ComplianceAction `mapstructure:"missing-name" json:"missing-name" yaml:"missing-name"`
|
||||||
|
MissingVersion cataloging.ComplianceAction `mapstructure:"missing-version" json:"missing-version" yaml:"missing-version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultComplianceConfig() complianceConfig {
|
||||||
|
def := cataloging.DefaultComplianceConfig()
|
||||||
|
return complianceConfig{
|
||||||
|
MissingName: def.MissingName,
|
||||||
|
MissingVersion: def.MissingVersion,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *complianceConfig) DescribeFields(descriptions fangs.FieldDescriptionSet) {
|
||||||
|
descriptions.Add(&r.MissingName, "action to take when a package is missing a name")
|
||||||
|
descriptions.Add(&r.MissingVersion, "action to take when a package is missing a version")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *complianceConfig) PostLoad() error {
|
||||||
|
r.MissingName = r.MissingName.Parse()
|
||||||
|
r.MissingVersion = r.MissingVersion.Parse()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -2,11 +2,11 @@ package options
|
|||||||
|
|
||||||
import "github.com/anchore/fangs"
|
import "github.com/anchore/fangs"
|
||||||
|
|
||||||
// Config holds a reference to the specific config file that was used to load application configuration
|
// Config holds a reference to the specific config file(s) that were used to load application configuration
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ConfigFile string `yaml:"config" json:"config" mapstructure:"config"`
|
ConfigFile string `yaml:"config" json:"config" mapstructure:"config"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg *Config) DescribeFields(descriptions fangs.FieldDescriptionSet) {
|
func (cfg *Config) DescribeFields(descriptions fangs.FieldDescriptionSet) {
|
||||||
descriptions.Add(&cfg.ConfigFile, "the configuration file that was used to load application configuration")
|
descriptions.Add(&cfg.ConfigFile, "the configuration file(s) used to load application configuration")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,7 +50,7 @@ if false, uses the syft-json output for templating (which follows the syft JSON
|
|||||||
|
|
||||||
Note: long term support for this option is not guaranteed (it may change or break at any time)`)
|
Note: long term support for this option is not guaranteed (it may change or break at any time)`)
|
||||||
|
|
||||||
prettyDescription := `include space indention and newlines
|
prettyDescription := `include space indentation and newlines
|
||||||
note: inherits default value from 'format.pretty' or 'false' if parent is unset`
|
note: inherits default value from 'format.pretty' or 'false' if parent is unset`
|
||||||
descriptions.Add(&o.SyftJSON.Pretty, prettyDescription)
|
descriptions.Add(&o.SyftJSON.Pretty, prettyDescription)
|
||||||
descriptions.Add(&o.SPDXJSON.Pretty, prettyDescription)
|
descriptions.Add(&o.SPDXJSON.Pretty, prettyDescription)
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type golangConfig struct {
|
type golangConfig struct {
|
||||||
SearchLocalModCacheLicenses bool `json:"search-local-mod-cache-licenses" yaml:"search-local-mod-cache-licenses" mapstructure:"search-local-mod-cache-licenses"`
|
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"`
|
LocalModCacheDir string `json:"local-mod-cache-dir" yaml:"local-mod-cache-dir" mapstructure:"local-mod-cache-dir"`
|
||||||
SearchRemoteLicenses bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"`
|
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"`
|
Proxy string `json:"proxy" yaml:"proxy" mapstructure:"proxy"`
|
||||||
NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"`
|
NoProxy string `json:"no-proxy" yaml:"no-proxy" mapstructure:"no-proxy"`
|
||||||
MainModuleVersion golangMainModuleVersionConfig `json:"main-module-version" yaml:"main-module-version" mapstructure:"main-module-version"`
|
MainModuleVersion golangMainModuleVersionConfig `json:"main-module-version" yaml:"main-module-version" mapstructure:"main-module-version"`
|
||||||
@@ -24,6 +26,9 @@ 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
|
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`)
|
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.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.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,
|
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`)
|
if unset this defaults to $GOPROXY followed by https://proxy.golang.org`)
|
||||||
@@ -47,9 +52,11 @@ type golangMainModuleVersionConfig struct {
|
|||||||
func defaultGolangConfig() golangConfig {
|
func defaultGolangConfig() golangConfig {
|
||||||
def := golang.DefaultCatalogerConfig()
|
def := golang.DefaultCatalogerConfig()
|
||||||
return golangConfig{
|
return golangConfig{
|
||||||
SearchLocalModCacheLicenses: def.SearchLocalModCacheLicenses,
|
SearchLocalModCacheLicenses: nil, // this defaults to false, which is the API default
|
||||||
LocalModCacheDir: def.LocalModCacheDir,
|
LocalModCacheDir: def.LocalModCacheDir,
|
||||||
SearchRemoteLicenses: def.SearchRemoteLicenses,
|
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, ","),
|
Proxy: strings.Join(def.Proxies, ","),
|
||||||
NoProxy: strings.Join(def.NoProxy, ","),
|
NoProxy: strings.Join(def.NoProxy, ","),
|
||||||
MainModuleVersion: golangMainModuleVersionConfig{
|
MainModuleVersion: golangMainModuleVersionConfig{
|
||||||
|
|||||||
@@ -1,11 +1,30 @@
|
|||||||
package options
|
package options
|
||||||
|
|
||||||
import "github.com/anchore/clio"
|
import (
|
||||||
|
"github.com/anchore/clio"
|
||||||
|
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
||||||
|
)
|
||||||
|
|
||||||
type javaConfig struct {
|
type javaConfig struct {
|
||||||
UseNetwork bool `yaml:"use-network" json:"use-network" mapstructure:"use-network"`
|
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"`
|
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"`
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ interface {
|
var _ interface {
|
||||||
@@ -13,12 +32,18 @@ var _ interface {
|
|||||||
} = (*javaConfig)(nil)
|
} = (*javaConfig)(nil)
|
||||||
|
|
||||||
func (o *javaConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
func (o *javaConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||||
descriptions.Add(&o.UseNetwork, `enables Syft to use the network to fill in more detailed information about artifacts
|
descriptions.Add(&o.UseNetwork, `enables Syft to use the network to fetch version and license information for packages when
|
||||||
currently this enables searching maven-url for license data
|
a parent or imported pom file is not found in the local maven repository.
|
||||||
when running across pom.xml files that could have more information, syft will
|
the pom files are downloaded from the remote Maven repository at 'maven-url'`)
|
||||||
explicitly search maven for license information by querying the online pom when this is true
|
|
||||||
this option is helpful for when the parent pom has more data,
|
|
||||||
that is not accessible from within the final built artifact`)
|
|
||||||
descriptions.Add(&o.MavenURL, `maven repository to use, defaults to Maven central`)
|
descriptions.Add(&o.MavenURL, `maven repository to use, defaults to Maven central`)
|
||||||
descriptions.Add(&o.MaxParentRecursiveDepth, `depth to recursively resolve parent POMs`)
|
descriptions.Add(&o.MaxParentRecursiveDepth, `depth to recursively resolve parent POMs, no limit if <= 0`)
|
||||||
|
descriptions.Add(&o.UseMavenLocalRepository, `use the local Maven repository to retrieve pom files. When Maven is installed and was previously used
|
||||||
|
for building the software that is being scanned, then most pom files will be available in this
|
||||||
|
repository on the local file system. this greatly speeds up scans. when all pom files are available
|
||||||
|
in the local repository, then 'use-network' is not needed.
|
||||||
|
TIP: If you want to download all required pom files to the local repository without running a full
|
||||||
|
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,8 +3,9 @@ package options
|
|||||||
import "github.com/anchore/clio"
|
import "github.com/anchore/clio"
|
||||||
|
|
||||||
type javaScriptConfig struct {
|
type javaScriptConfig struct {
|
||||||
SearchRemoteLicenses bool `json:"search-remote-licenses" yaml:"search-remote-licenses" mapstructure:"search-remote-licenses"`
|
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"`
|
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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ interface {
|
var _ interface {
|
||||||
@@ -14,4 +15,5 @@ var _ interface {
|
|||||||
func (o *javaScriptConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
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.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.NpmBaseURL, `base NPM url to use`)
|
||||||
|
descriptions.Add(&o.IncludeDevDependencies, `include development-scoped dependencies`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
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,6 +12,7 @@ import (
|
|||||||
"github.com/anchore/syft/syft/format/cyclonedxjson"
|
"github.com/anchore/syft/syft/format/cyclonedxjson"
|
||||||
"github.com/anchore/syft/syft/format/cyclonedxxml"
|
"github.com/anchore/syft/syft/format/cyclonedxxml"
|
||||||
"github.com/anchore/syft/syft/format/github"
|
"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/spdxjson"
|
||||||
"github.com/anchore/syft/syft/format/spdxtagvalue"
|
"github.com/anchore/syft/syft/format/spdxtagvalue"
|
||||||
"github.com/anchore/syft/syft/format/syftjson"
|
"github.com/anchore/syft/syft/format/syftjson"
|
||||||
@@ -89,7 +90,7 @@ func (o Output) SBOMWriter() (sbom.Writer, error) {
|
|||||||
|
|
||||||
usesTemplateOutput := names.Has(string(template.ID))
|
usesTemplateOutput := names.Has(string(template.ID))
|
||||||
|
|
||||||
if usesTemplateOutput && o.Format.Template.Path == "" {
|
if usesTemplateOutput && o.Template.Path == "" {
|
||||||
return nil, fmt.Errorf(`must specify path to template file when using "template" output format`)
|
return nil, fmt.Errorf(`must specify path to template file when using "template" output format`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,6 +128,7 @@ func supportedIDs() []sbom.FormatID {
|
|||||||
table.ID,
|
table.ID,
|
||||||
text.ID,
|
text.ID,
|
||||||
template.ID,
|
template.ID,
|
||||||
|
purls.ID,
|
||||||
|
|
||||||
// encoders that support multiple versions
|
// encoders that support multiple versions
|
||||||
cyclonedxxml.ID,
|
cyclonedxxml.ID,
|
||||||
|
|||||||
@@ -3,10 +3,9 @@ package options
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mitchellh/go-homedir"
|
|
||||||
|
|
||||||
"github.com/anchore/clio"
|
"github.com/anchore/clio"
|
||||||
"github.com/anchore/fangs"
|
"github.com/anchore/fangs"
|
||||||
|
"github.com/anchore/go-homedir"
|
||||||
"github.com/anchore/syft/syft/sbom"
|
"github.com/anchore/syft/syft/sbom"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,7 +27,7 @@ func (o *OutputFile) AddFlags(flags clio.FlagSet) {
|
|||||||
|
|
||||||
if pfp, ok := flags.(fangs.PFlagSetProvider); ok {
|
if pfp, ok := flags.(fangs.PFlagSetProvider); ok {
|
||||||
flagSet := pfp.PFlagSet()
|
flagSet := pfp.PFlagSet()
|
||||||
flagSet.Lookup("file").Deprecated = "use: output"
|
flagSet.Lookup("file").Deprecated = "use: --output FORMAT=PATH"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ var _ interface {
|
|||||||
} = (*packageConfig)(nil)
|
} = (*packageConfig)(nil)
|
||||||
|
|
||||||
func (o *packageConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
func (o *packageConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
||||||
descriptions.Add(&o.SearchUnindexedArchives, `search within archives that do contain a file index to search against (zip)
|
descriptions.Add(&o.SearchIndexedArchives, `search within archives that do contain a file index to search against (zip)
|
||||||
note: for now this only applies to the java package cataloger`)
|
note: for now this only applies to the java package cataloger`)
|
||||||
descriptions.Add(&o.SearchIndexedArchives, `search within archives that do not contain a file index to search against (tar, tar.gz, tar.bz2, etc)
|
descriptions.Add(&o.SearchUnindexedArchives, `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: 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`)
|
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
|
descriptions.Add(&o.ExcludeBinaryOverlapByOwnership, `allows users to exclude synthetic binary packages from the sbom
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/dustin/go-humanize"
|
||||||
"github.com/scylladb/go-set/strset"
|
"github.com/scylladb/go-set/strset"
|
||||||
|
|
||||||
"github.com/anchore/clio"
|
"github.com/anchore/clio"
|
||||||
|
stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/syft/syft/source/sourceproviders"
|
"github.com/anchore/syft/syft/source/sourceproviders"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -27,6 +29,8 @@ var _ interface {
|
|||||||
clio.FieldDescriber
|
clio.FieldDescriber
|
||||||
} = (*sourceConfig)(nil)
|
} = (*sourceConfig)(nil)
|
||||||
|
|
||||||
|
var _ clio.PostLoader = (*imageSource)(nil)
|
||||||
|
|
||||||
func (o *sourceConfig) DescribeFields(descriptions clio.FieldDescriptionSet) {
|
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.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
|
descriptions.Add(&o.Image.DefaultPullSource, `allows users to specify which image source should be used to generate the sbom
|
||||||
@@ -35,6 +39,7 @@ valid values are: registry, docker, podman`)
|
|||||||
|
|
||||||
type imageSource struct {
|
type imageSource struct {
|
||||||
DefaultPullSource string `json:"default-pull-source" yaml:"default-pull-source" mapstructure:"default-pull-source"`
|
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 {
|
func defaultSourceConfig() sourceConfig {
|
||||||
@@ -56,7 +61,14 @@ func (c *fileSource) PostLoad() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c imageSource) PostLoad() error {
|
func (c *imageSource) PostLoad() error {
|
||||||
|
if c.MaxLayerSize != "" {
|
||||||
|
perFileReadLimit, err := humanize.ParseBytes(c.MaxLayerSize)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stereoscopeFile.SetPerFileReadLimit(int64(perFileReadLimit))
|
||||||
|
}
|
||||||
return checkDefaultSourceValues(c.DefaultPullSource)
|
return checkDefaultSourceValues(c.DefaultPullSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
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"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/mitchellh/go-homedir"
|
|
||||||
"github.com/scylladb/go-set/strset"
|
"github.com/scylladb/go-set/strset"
|
||||||
|
|
||||||
|
"github.com/anchore/go-homedir"
|
||||||
"github.com/anchore/syft/internal/bus"
|
"github.com/anchore/syft/internal/bus"
|
||||||
"github.com/anchore/syft/internal/log"
|
"github.com/anchore/syft/internal/log"
|
||||||
"github.com/anchore/syft/syft/format"
|
"github.com/anchore/syft/syft/format"
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/homedir"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/anchore/go-homedir"
|
||||||
"github.com/anchore/syft/syft/sbom"
|
"github.com/anchore/syft/syft/sbom"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -228,6 +228,8 @@ func Test_newSBOMMultiWriter(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_newSBOMWriterDescription(t *testing.T) {
|
func Test_newSBOMWriterDescription(t *testing.T) {
|
||||||
|
h, err := homedir.Dir()
|
||||||
|
require.NoError(t, err)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
path string
|
path string
|
||||||
@@ -236,7 +238,7 @@ func Test_newSBOMWriterDescription(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "expand home dir",
|
name: "expand home dir",
|
||||||
path: "~/place.txt",
|
path: "~/place.txt",
|
||||||
expected: filepath.Join(homedir.Get(), "place.txt"),
|
expected: filepath.Join(h, "place.txt"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "passthrough other paths",
|
name: "passthrough other paths",
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
results
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Test_AllLayersIncludesSquashed(t *testing.T) {
|
func Test_AllLayersIncludesSquashed(t *testing.T) {
|
||||||
// This is a verification test for issue #894 (https://github.com/anchore/syft/issues/894)
|
// This is a verification test for issue grype/#894 (https://github.com/anchore/grype/issues/894)
|
||||||
allLayers, _ := catalogFixtureImage(t, "image-suse-all-layers", source.AllLayersScope)
|
allLayers, _ := catalogFixtureImage(t, "image-suse-all-layers", source.AllLayersScope)
|
||||||
squashed, _ := catalogFixtureImage(t, "image-suse-all-layers", source.SquashedScope)
|
squashed, _ := catalogFixtureImage(t, "image-suse-all-layers", source.SquashedScope)
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ var imageOnlyTestCases = []testCase{
|
|||||||
pkgType: pkg.PythonPkg,
|
pkgType: pkg.PythonPkg,
|
||||||
pkgLanguage: pkg.Python,
|
pkgLanguage: pkg.Python,
|
||||||
pkgInfo: map[string]string{
|
pkgInfo: map[string]string{
|
||||||
"Pygments": "2.6.1",
|
"pygments": "2.6.1",
|
||||||
"requests": "2.22.0",
|
"requests": "2.22.0",
|
||||||
"somerequests": "3.22.0",
|
"somerequests": "3.22.0",
|
||||||
"someotherpkg": "3.19.0",
|
"someotherpkg": "3.19.0",
|
||||||
@@ -78,11 +78,27 @@ var imageOnlyTestCases = []testCase{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "find dot net executable",
|
name: "find .NET packages (deps.json + .dlls)",
|
||||||
pkgType: pkg.DotnetPkg,
|
pkgType: pkg.DotnetPkg,
|
||||||
pkgLanguage: pkg.Dotnet,
|
pkgLanguage: pkg.Dotnet,
|
||||||
pkgInfo: map[string]string{
|
pkgInfo: map[string]string{
|
||||||
|
// executable
|
||||||
"DocuSign.eSign": "6.8.0.0",
|
"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",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -172,7 +188,7 @@ var dirOnlyTestCases = []testCase{
|
|||||||
"passlib": "1.7.2",
|
"passlib": "1.7.2",
|
||||||
"mypy": "v0.770",
|
"mypy": "v0.770",
|
||||||
// common to image and directory
|
// common to image and directory
|
||||||
"Pygments": "2.6.1",
|
"pygments": "2.6.1",
|
||||||
"requests": "2.22.0",
|
"requests": "2.22.0",
|
||||||
"somerequests": "3.22.0",
|
"somerequests": "3.22.0",
|
||||||
"someotherpkg": "3.19.0",
|
"someotherpkg": "3.19.0",
|
||||||
@@ -241,10 +257,11 @@ var dirOnlyTestCases = []testCase{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "find dotnet packages",
|
name: "find dotnet packages (.deps.json)",
|
||||||
pkgType: pkg.DotnetPkg,
|
pkgType: pkg.DotnetPkg,
|
||||||
pkgLanguage: pkg.Dotnet,
|
pkgLanguage: pkg.Dotnet,
|
||||||
pkgInfo: map[string]string{
|
pkgInfo: map[string]string{
|
||||||
|
// all from deps.json
|
||||||
"AWSSDK.Core": "3.7.10.6",
|
"AWSSDK.Core": "3.7.10.6",
|
||||||
"Microsoft.Extensions.DependencyInjection": "6.0.0",
|
"Microsoft.Extensions.DependencyInjection": "6.0.0",
|
||||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
"Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0",
|
||||||
@@ -255,8 +272,8 @@ var dirOnlyTestCases = []testCase{
|
|||||||
"Newtonsoft.Json": "13.0.1",
|
"Newtonsoft.Json": "13.0.1",
|
||||||
"Serilog": "2.10.0",
|
"Serilog": "2.10.0",
|
||||||
"Serilog.Sinks.Console": "4.0.1",
|
"Serilog.Sinks.Console": "4.0.1",
|
||||||
"System.Diagnostics.DiagnosticSource": "6.0.0",
|
//"System.Diagnostics.DiagnosticSource": "6.0.0", // no dll claims in deps.json targets section
|
||||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
|
//"System.Runtime.CompilerServices.Unsafe": "6.0.0", // no dll claims in deps.json targets section
|
||||||
"TestCommon": "1.0.0",
|
"TestCommon": "1.0.0",
|
||||||
"TestLibrary": "1.0.0",
|
"TestLibrary": "1.0.0",
|
||||||
},
|
},
|
||||||
@@ -265,7 +282,7 @@ var dirOnlyTestCases = []testCase{
|
|||||||
name: "find java packages including pom.xml", // directory scans can include packages that have yet to be installed
|
name: "find java packages including pom.xml", // directory scans can include packages that have yet to be installed
|
||||||
pkgType: pkg.JavaPkg,
|
pkgType: pkg.JavaPkg,
|
||||||
pkgLanguage: pkg.Java,
|
pkgLanguage: pkg.Java,
|
||||||
duplicates: 1, // joda-time is included in both pom.xml AND the .jar collection
|
duplicates: 2, // joda-time and example-java-app-maven are included in both pom.xml AND the .jar collection
|
||||||
pkgInfo: map[string]string{
|
pkgInfo: map[string]string{
|
||||||
"example-java-app-maven": "0.1.0",
|
"example-java-app-maven": "0.1.0",
|
||||||
"joda-time": "2.9.2",
|
"joda-time": "2.9.2",
|
||||||
@@ -388,6 +405,14 @@ var dirOnlyTestCases = []testCase{
|
|||||||
"swift-numerics": "1.0.2",
|
"swift-numerics": "1.0.2",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "find swipl pack package manager packages",
|
||||||
|
pkgType: pkg.SwiplPackPkg,
|
||||||
|
pkgLanguage: pkg.Swipl,
|
||||||
|
pkgInfo: map[string]string{
|
||||||
|
"hdt": "0.5.2",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "find github action packages (from usage in workflow files and composite actions)",
|
name: "find github action packages (from usage in workflow files and composite actions)",
|
||||||
pkgType: pkg.GithubActionPkg,
|
pkgType: pkg.GithubActionPkg,
|
||||||
@@ -402,6 +427,22 @@ var dirOnlyTestCases = []testCase{
|
|||||||
"octo-org/this-repo/.github/workflows/workflow-1.yml": "172239021f7ba04fe7327647b213799853a9eb89",
|
"octo-org/this-repo/.github/workflows/workflow-1.yml": "172239021f7ba04fe7327647b213799853a9eb89",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "find opam package",
|
||||||
|
pkgType: pkg.OpamPkg,
|
||||||
|
pkgLanguage: pkg.OCaml,
|
||||||
|
pkgInfo: map[string]string{
|
||||||
|
"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{
|
var commonTestCases = []testCase{
|
||||||
@@ -461,8 +502,15 @@ var commonTestCases = []testCase{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "find php pecl package",
|
name: "find homebrew",
|
||||||
pkgType: pkg.PhpPeclPkg,
|
pkgType: pkg.HomebrewPkg,
|
||||||
|
pkgInfo: map[string]string{
|
||||||
|
"afflib": "1.2.3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "find php pear/pecl package",
|
||||||
|
pkgType: pkg.PhpPearPkg,
|
||||||
pkgLanguage: pkg.PHP,
|
pkgLanguage: pkg.PHP,
|
||||||
pkgInfo: map[string]string{
|
pkgInfo: map[string]string{
|
||||||
"memcached": "3.2.0",
|
"memcached": "3.2.0",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/anchore/stereoscope/pkg/imagetest"
|
"github.com/anchore/stereoscope/pkg/imagetest"
|
||||||
"github.com/anchore/syft/syft"
|
"github.com/anchore/syft/syft"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/sbom"
|
||||||
"github.com/anchore/syft/syft/source"
|
"github.com/anchore/syft/syft/source"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -51,6 +52,8 @@ func TestPkgCoverageImage(t *testing.T) {
|
|||||||
definedLanguages.Remove(pkg.Rust.String())
|
definedLanguages.Remove(pkg.Rust.String())
|
||||||
definedLanguages.Remove(pkg.Dart.String())
|
definedLanguages.Remove(pkg.Dart.String())
|
||||||
definedLanguages.Remove(pkg.Swift.String())
|
definedLanguages.Remove(pkg.Swift.String())
|
||||||
|
definedLanguages.Remove(pkg.Swipl.String())
|
||||||
|
definedLanguages.Remove(pkg.OCaml.String())
|
||||||
definedLanguages.Remove(pkg.CPP.String())
|
definedLanguages.Remove(pkg.CPP.String())
|
||||||
definedLanguages.Remove(pkg.Haskell.String())
|
definedLanguages.Remove(pkg.Haskell.String())
|
||||||
definedLanguages.Remove(pkg.Elixir.String())
|
definedLanguages.Remove(pkg.Elixir.String())
|
||||||
@@ -72,12 +75,18 @@ func TestPkgCoverageImage(t *testing.T) {
|
|||||||
definedPkgs.Remove(string(pkg.ConanPkg))
|
definedPkgs.Remove(string(pkg.ConanPkg))
|
||||||
definedPkgs.Remove(string(pkg.HackagePkg))
|
definedPkgs.Remove(string(pkg.HackagePkg))
|
||||||
definedPkgs.Remove(string(pkg.BinaryPkg))
|
definedPkgs.Remove(string(pkg.BinaryPkg))
|
||||||
|
definedPkgs.Remove(string(pkg.BitnamiPkg))
|
||||||
|
definedPkgs.Remove(string(pkg.GraalVMNativeImagePkg))
|
||||||
definedPkgs.Remove(string(pkg.HexPkg))
|
definedPkgs.Remove(string(pkg.HexPkg))
|
||||||
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
|
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
|
||||||
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
|
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
|
||||||
definedPkgs.Remove(string(pkg.SwiftPkg))
|
definedPkgs.Remove(string(pkg.SwiftPkg))
|
||||||
|
definedPkgs.Remove(string(pkg.SwiplPackPkg))
|
||||||
|
definedPkgs.Remove(string(pkg.OpamPkg))
|
||||||
definedPkgs.Remove(string(pkg.GithubActionPkg))
|
definedPkgs.Remove(string(pkg.GithubActionPkg))
|
||||||
definedPkgs.Remove(string(pkg.GithubActionWorkflowPkg))
|
definedPkgs.Remove(string(pkg.GithubActionWorkflowPkg))
|
||||||
|
definedPkgs.Remove(string(pkg.TerraformPkg))
|
||||||
|
definedPkgs.Remove(string(pkg.PhpPeclPkg)) // we have coverage for pear instead
|
||||||
|
|
||||||
var cases []testCase
|
var cases []testCase
|
||||||
cases = append(cases, commonTestCases...)
|
cases = append(cases, commonTestCases...)
|
||||||
@@ -85,40 +94,7 @@ func TestPkgCoverageImage(t *testing.T) {
|
|||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(c.name, func(t *testing.T) {
|
||||||
pkgCount := 0
|
assertPackages(t, sbom, c, observedLanguages, observedPkgs)
|
||||||
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,6 +144,37 @@ func TestPkgCoverageDirectory(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range cases {
|
for _, test := range cases {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
assertPackages(t, sbom, test, observedLanguages, observedPkgs)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
observedLanguages.Remove(pkg.UnknownLanguage.String())
|
||||||
|
definedLanguages.Remove(pkg.UnknownLanguage.String())
|
||||||
|
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.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))
|
||||||
|
|
||||||
|
// ensure that integration test commonTestCases stay in sync with the available catalogers
|
||||||
|
if observedLanguages.Size() < definedLanguages.Size() {
|
||||||
|
t.Errorf("language coverage incomplete (languages=%d, coverage=%d)", definedLanguages.Size(), observedLanguages.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
if observedPkgs.Size() < definedPkgs.Size() {
|
||||||
|
t.Errorf("package coverage incomplete (packages=%d, coverage=%d)", definedPkgs.Size(), observedPkgs.Size())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertPackages(t *testing.T, sbom sbom.SBOM, test testCase, observedLanguages *strset.Set, observedPkgs *strset.Set) {
|
||||||
actualPkgCount := 0
|
actualPkgCount := 0
|
||||||
|
|
||||||
for actualPkg := range sbom.Artifacts.Packages.Enumerate(test.pkgType) {
|
for actualPkg := range sbom.Artifacts.Packages.Enumerate(test.pkgType) {
|
||||||
@@ -198,6 +205,20 @@ func TestPkgCoverageDirectory(t *testing.T) {
|
|||||||
t.Errorf("bad package type (pkg=%+v): %+v", actualPkg.Name, actualPkg.Type)
|
t.Errorf("bad package type (pkg=%+v): %+v", actualPkg.Name, actualPkg.Type)
|
||||||
}
|
}
|
||||||
actualPkgCount++
|
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 {
|
if actualPkgCount != len(test.pkgInfo)+test.duplicates {
|
||||||
@@ -206,30 +227,6 @@ func TestPkgCoverageDirectory(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Fatalf("unexpected package count: %d!=%d", actualPkgCount, len(test.pkgInfo))
|
t.Fatalf("unexpected package count: %d!=%d", actualPkgCount, len(test.pkgInfo))
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
observedLanguages.Remove(pkg.UnknownLanguage.String())
|
|
||||||
definedLanguages.Remove(pkg.UnknownLanguage.String())
|
|
||||||
definedLanguages.Remove(pkg.R.String())
|
|
||||||
observedPkgs.Remove(string(pkg.UnknownPkg))
|
|
||||||
definedPkgs.Remove(string(pkg.BinaryPkg))
|
|
||||||
definedPkgs.Remove(string(pkg.LinuxKernelPkg))
|
|
||||||
definedPkgs.Remove(string(pkg.LinuxKernelModulePkg))
|
|
||||||
definedPkgs.Remove(string(pkg.Rpkg))
|
|
||||||
definedPkgs.Remove(string(pkg.UnknownPkg))
|
|
||||||
|
|
||||||
// for directory scans we should not expect to see any of the following package types
|
|
||||||
definedPkgs.Remove(string(pkg.KbPkg))
|
|
||||||
|
|
||||||
// ensure that integration test commonTestCases stay in sync with the available catalogers
|
|
||||||
if observedLanguages.Size() < definedLanguages.Size() {
|
|
||||||
t.Errorf("language coverage incomplete (languages=%d, coverage=%d)", definedLanguages.Size(), observedLanguages.Size())
|
|
||||||
}
|
|
||||||
|
|
||||||
if observedPkgs.Size() < definedPkgs.Size() {
|
|
||||||
t.Errorf("package coverage incomplete (packages=%d, coverage=%d)", definedPkgs.Size(), observedPkgs.Size())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPkgCoverageImage_HasEvidence(t *testing.T) {
|
func TestPkgCoverageImage_HasEvidence(t *testing.T) {
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package integration
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"regexp"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
@@ -12,8 +14,6 @@ import (
|
|||||||
|
|
||||||
"github.com/anchore/syft/cmd/syft/internal/options"
|
"github.com/anchore/syft/cmd/syft/internal/options"
|
||||||
"github.com/anchore/syft/syft/format"
|
"github.com/anchore/syft/syft/format"
|
||||||
"github.com/anchore/syft/syft/format/cyclonedxjson"
|
|
||||||
"github.com/anchore/syft/syft/format/cyclonedxxml"
|
|
||||||
"github.com/anchore/syft/syft/format/syftjson"
|
"github.com/anchore/syft/syft/format/syftjson"
|
||||||
"github.com/anchore/syft/syft/source"
|
"github.com/anchore/syft/syft/source"
|
||||||
)
|
)
|
||||||
@@ -43,26 +43,27 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
|
|||||||
},
|
},
|
||||||
json: true,
|
json: true,
|
||||||
},
|
},
|
||||||
{
|
// TODO: ignoring the `ref` field though does create stable results to compare, but the SBOM is fundamentally gutted and not worth comparing (find a better redaction or compare method)
|
||||||
name: cyclonedxjson.ID.String(),
|
//{
|
||||||
redactor: func(in []byte) []byte {
|
// name: cyclonedxjson.ID.String(),
|
||||||
// unstable values
|
// redactor: func(in []byte) []byte {
|
||||||
in = regexp.MustCompile(`"(timestamp|serialNumber|bom-ref|ref)":\s*"(\n|[^"])+"`).ReplaceAll(in, []byte(`"$1": "redacted"`))
|
// // unstable values
|
||||||
in = regexp.MustCompile(`"(dependsOn)":\s*\[(?:\s|[^]])+]`).ReplaceAll(in, []byte(`"$1": []`))
|
// in = regexp.MustCompile(`"(timestamp|serialNumber|bom-ref|ref)":\s*"(\n|[^"])+"`).ReplaceAll(in, []byte(`"$1": "redacted"`))
|
||||||
return in
|
// in = regexp.MustCompile(`"(dependsOn)":\s*\[(?:\s|[^]])+]`).ReplaceAll(in, []byte(`"$1": []`))
|
||||||
},
|
// return in
|
||||||
json: true,
|
// },
|
||||||
},
|
// json: true,
|
||||||
{
|
//},
|
||||||
name: cyclonedxxml.ID.String(),
|
//{
|
||||||
redactor: func(in []byte) []byte {
|
// name: cyclonedxxml.ID.String(),
|
||||||
// unstable values
|
// redactor: func(in []byte) []byte {
|
||||||
in = regexp.MustCompile(`(serialNumber|bom-ref|ref)="[^"]+"`).ReplaceAll(in, []byte{})
|
// // unstable values
|
||||||
in = regexp.MustCompile(`<timestamp>[^<]+</timestamp>`).ReplaceAll(in, []byte{})
|
// in = regexp.MustCompile(`(serialNumber|bom-ref|ref)="[^"]+"`).ReplaceAll(in, []byte{})
|
||||||
|
// in = regexp.MustCompile(`<timestamp>[^<]+</timestamp>`).ReplaceAll(in, []byte{})
|
||||||
return in
|
//
|
||||||
},
|
// return in
|
||||||
},
|
// },
|
||||||
|
//},
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := options.DefaultOutput()
|
opts := options.DefaultOutput()
|
||||||
@@ -112,6 +113,21 @@ func TestEncodeDecodeEncodeCycleComparison(t *testing.T) {
|
|||||||
diffs := dmp.DiffMain(string(by1), string(by2), true)
|
diffs := dmp.DiffMain(string(by1), string(by2), true)
|
||||||
t.Errorf("diff: %s", dmp.DiffPrettyText(diffs))
|
t.Errorf("diff: %s", dmp.DiffPrettyText(diffs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write raw IMAGE@NAME-start and IMAGE@NAME-finish to files within the results dir
|
||||||
|
// ... this is helpful for debugging
|
||||||
|
require.NoError(t, os.MkdirAll("results", 0700))
|
||||||
|
|
||||||
|
suffix := "sbom"
|
||||||
|
switch {
|
||||||
|
case strings.Contains(test.name, "json"):
|
||||||
|
suffix = "json"
|
||||||
|
case strings.Contains(test.name, "xml"):
|
||||||
|
suffix = "xml"
|
||||||
|
}
|
||||||
|
|
||||||
|
require.NoError(t, os.WriteFile(filepath.Join("results", image+"@"+test.name+"-start."+suffix), by1, 0600))
|
||||||
|
require.NoError(t, os.WriteFile(filepath.Join("results", image+"@"+test.name+"-finish."+suffix), by2, 0600))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ func TestGolangCompilerDetection(t *testing.T) {
|
|||||||
for _, pkg := range packages {
|
for _, pkg := range packages {
|
||||||
foundCompilerVersions[pkg.Version] = struct{}{}
|
foundCompilerVersions[pkg.Version] = struct{}{}
|
||||||
foundPURL[pkg.PURL] = struct{}{}
|
foundPURL[pkg.PURL] = struct{}{}
|
||||||
for _, cpe := range pkg.CPEs {
|
for _, c := range pkg.CPEs {
|
||||||
foundCPE[cpe] = struct{}{}
|
foundCPE[c] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
"github.com/anchore/syft/syft/source"
|
"github.com/anchore/syft/syft/source"
|
||||||
@@ -26,13 +25,9 @@ func TestJavaPURLs(t *testing.T) {
|
|||||||
found[metadata.VirtualPath] = p.PURL
|
found[metadata.VirtualPath] = p.PURL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for key, expectedPURL := range expectedPURLs {
|
|
||||||
purl := found[key]
|
if d := cmp.Diff(expectedPURLs, found); d != "" {
|
||||||
assert.Equal(t, expectedPURL, purl, fmt.Sprintf("found wrong or missing PURL for %s want %s, got %s", key, expectedPURL, purl))
|
t.Errorf("unexpected purl values:\n%s", d)
|
||||||
}
|
|
||||||
for key, foundPURL := range found {
|
|
||||||
expectedPURL := expectedPURLs[key]
|
|
||||||
assert.Equal(t, expectedPURL, foundPURL, fmt.Sprintf("found extra purl for %s want %s, got %s", key, expectedPURL, foundPURL))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,9 +36,101 @@ func TestJavaPURLs(t *testing.T) {
|
|||||||
// generating the incorrect PURL
|
// generating the incorrect PURL
|
||||||
var noAssertion = map[string]string{
|
var noAssertion = map[string]string{
|
||||||
// These are not known to exist on any public maven repo, so no real PURL should be asserted
|
// These are not known to exist on any public maven repo, so no real PURL should be asserted
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/trilead-ssh2-build-217-jenkins-27.jar": "pkg:maven/trilead-ssh2-build/trilead-ssh2-build@217-jenkins-27",
|
||||||
|
// possibly org.gradle as groupid for these, but unclear
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-api-metadata-7.1.1.jar": "pkg:maven/gradle-api-metadata/gradle-api-metadata@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-base-annotations-7.1.1.jar": "pkg:maven/gradle-base-annotations/gradle-base-annotations@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-base-services-7.1.1.jar": "pkg:maven/gradle-base-services/gradle-base-services@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-base-services-groovy-7.1.1.jar": "pkg:maven/gradle-base-services-groovy/gradle-base-services-groovy@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-bootstrap-7.1.1.jar": "pkg:maven/gradle-bootstrap/gradle-bootstrap@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-build-cache-7.1.1.jar": "pkg:maven/gradle-build-cache/gradle-build-cache@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-build-cache-base-7.1.1.jar": "pkg:maven/gradle-build-cache-base/gradle-build-cache-base@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-build-cache-packaging-7.1.1.jar": "pkg:maven/gradle-build-cache-packaging/gradle-build-cache-packaging@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-build-events-7.1.1.jar": "pkg:maven/gradle-build-events/gradle-build-events@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-build-operations-7.1.1.jar": "pkg:maven/gradle-build-operations/gradle-build-operations@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-build-option-7.1.1.jar": "pkg:maven/gradle-build-option/gradle-build-option@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-cli-7.1.1.jar": "pkg:maven/gradle-cli/gradle-cli@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-core-7.1.1.jar": "pkg:maven/gradle-core/gradle-core@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-core-api-7.1.1.jar": "pkg:maven/gradle-core-api/gradle-core-api@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-data-structures-7.1.1.jar": "pkg:maven/gradle-data-structures/gradle-data-structures@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-execution-7.1.1.jar": "pkg:maven/gradle-execution/gradle-execution@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-file-collections-7.1.1.jar": "pkg:maven/gradle-file-collections/gradle-file-collections@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-file-temp-7.1.1.jar": "pkg:maven/gradle-file-temp/gradle-file-temp@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-file-watching-7.1.1.jar": "pkg:maven/gradle-file-watching/gradle-file-watching@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-files-7.1.1.jar": "pkg:maven/gradle-files/gradle-files@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-hashing-7.1.1.jar": "pkg:maven/gradle-hashing/gradle-hashing@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-installation-beacon-7.1.1.jar": "pkg:maven/gradle-installation-beacon/gradle-installation-beacon@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-jvm-services-7.1.1.jar": "pkg:maven/gradle-jvm-services/gradle-jvm-services@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-kotlin-dsl-7.1.1.jar": "pkg:maven/gradle-kotlin-dsl/gradle-kotlin-dsl@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-kotlin-dsl-tooling-models-7.1.1.jar": "pkg:maven/gradle-kotlin-dsl-tooling-models/gradle-kotlin-dsl-tooling-models@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-launcher-7.1.1.jar": "pkg:maven/org.gradle.launcher.GradleMain/gradle-launcher@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-logging-7.1.1.jar": "pkg:maven/gradle-logging/gradle-logging@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-messaging-7.1.1.jar": "pkg:maven/gradle-messaging/gradle-messaging@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-model-core-7.1.1.jar": "pkg:maven/gradle-model-core/gradle-model-core@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-model-groovy-7.1.1.jar": "pkg:maven/gradle-model-groovy/gradle-model-groovy@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-native-7.1.1.jar": "pkg:maven/gradle-native/gradle-native@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-normalization-java-7.1.1.jar": "pkg:maven/gradle-normalization-java/gradle-normalization-java@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-persistent-cache-7.1.1.jar": "pkg:maven/gradle-persistent-cache/gradle-persistent-cache@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-problems-7.1.1.jar": "pkg:maven/gradle-problems/gradle-problems@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-process-services-7.1.1.jar": "pkg:maven/gradle-process-services/gradle-process-services@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-resources-7.1.1.jar": "pkg:maven/gradle-resources/gradle-resources@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-runtime-api-info-7.1.1.jar": "pkg:maven/gradle-runtime-api-info/gradle-runtime-api-info@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-snapshots-7.1.1.jar": "pkg:maven/gradle-snapshots/gradle-snapshots@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-tooling-api-7.1.1.jar": "pkg:maven/gradle-tooling-api/gradle-tooling-api@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-worker-processes-7.1.1.jar": "pkg:maven/gradle-worker-processes/gradle-worker-processes@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-wrapper-7.1.1.jar": "pkg:maven/gradle-wrapper/gradle-wrapper@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/gradle-wrapper-7.1.1.jar:gradle-wrapper.jar": "pkg:maven/gradle-wrapper/gradle-wrapper",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-antlr-7.1.1.jar": "pkg:maven/gradle-antlr/gradle-antlr@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-build-cache-http-7.1.1.jar": "pkg:maven/gradle-build-cache-http/gradle-build-cache-http@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-build-init-7.1.1.jar": "pkg:maven/gradle-build-init/gradle-build-init@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-build-profile-7.1.1.jar": "pkg:maven/gradle-build-profile/gradle-build-profile@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-code-quality-7.1.1.jar": "pkg:maven/gradle-code-quality/gradle-code-quality@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-composite-builds-7.1.1.jar": "pkg:maven/gradle-composite-builds/gradle-composite-builds@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-configuration-cache-7.1.1.jar": "pkg:maven/gradle-configuration-cache/gradle-configuration-cache@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-dependency-management-7.1.1.jar": "pkg:maven/gradle-dependency-management/gradle-dependency-management@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-diagnostics-7.1.1.jar": "pkg:maven/gradle-diagnostics/gradle-diagnostics@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-ear-7.1.1.jar": "pkg:maven/gradle-ear/gradle-ear@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-enterprise-7.1.1.jar": "pkg:maven/gradle-enterprise/gradle-enterprise@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-ide-7.1.1.jar": "pkg:maven/gradle-ide/gradle-ide@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-ide-native-7.1.1.jar": "pkg:maven/gradle-ide-native/gradle-ide-native@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-ivy-7.1.1.jar": "pkg:maven/gradle-ivy/gradle-ivy@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-jacoco-7.1.1.jar": "pkg:maven/gradle-jacoco/gradle-jacoco@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-java-compiler-plugin-7.1.1.jar": "pkg:maven/gradle-java-compiler-plugin/gradle-java-compiler-plugin@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-kotlin-dsl-provider-plugins-7.1.1.jar": "pkg:maven/gradle-kotlin-dsl-provider-plugins/gradle-kotlin-dsl-provider-plugins@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-kotlin-dsl-tooling-builders-7.1.1.jar": "pkg:maven/gradle-kotlin-dsl-tooling-builders/gradle-kotlin-dsl-tooling-builders@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-language-groovy-7.1.1.jar": "pkg:maven/gradle-language-groovy/gradle-language-groovy@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-language-java-7.1.1.jar": "pkg:maven/gradle-language-java/gradle-language-java@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-language-jvm-7.1.1.jar": "pkg:maven/gradle-language-jvm/gradle-language-jvm@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-language-native-7.1.1.jar": "pkg:maven/gradle-language-native/gradle-language-native@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-maven-7.1.1.jar": "pkg:maven/gradle-maven/gradle-maven@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-platform-base-7.1.1.jar": "pkg:maven/gradle-platform-base/gradle-platform-base@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-platform-jvm-7.1.1.jar": "pkg:maven/gradle-platform-jvm/gradle-platform-jvm@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-platform-native-7.1.1.jar": "pkg:maven/gradle-platform-native/gradle-platform-native@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-plugin-development-7.1.1.jar": "pkg:maven/gradle-plugin-development/gradle-plugin-development@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-plugin-use-7.1.1.jar": "pkg:maven/gradle-plugin-use/gradle-plugin-use@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-plugins-7.1.1.jar": "pkg:maven/gradle-plugins/gradle-plugins@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-publish-7.1.1.jar": "pkg:maven/gradle-publish/gradle-publish@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-reporting-7.1.1.jar": "pkg:maven/gradle-reporting/gradle-reporting@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-resources-gcs-7.1.1.jar": "pkg:maven/gradle-resources-gcs/gradle-resources-gcs@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-resources-http-7.1.1.jar": "pkg:maven/gradle-resources-http/gradle-resources-http@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-resources-s3-7.1.1.jar": "pkg:maven/gradle-resources-s3/gradle-resources-s3@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-resources-sftp-7.1.1.jar": "pkg:maven/gradle-resources-sftp/gradle-resources-sftp@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-scala-7.1.1.jar": "pkg:maven/gradle-scala/gradle-scala@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-security-7.1.1.jar": "pkg:maven/gradle-security/gradle-security@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-signing-7.1.1.jar": "pkg:maven/gradle-signing/gradle-signing@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-test-kit-7.1.1.jar": "pkg:maven/gradle-test-kit/gradle-test-kit@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-testing-base-7.1.1.jar": "pkg:maven/gradle-testing-base/gradle-testing-base@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-testing-junit-platform-7.1.1.jar": "pkg:maven/gradle-testing-junit-platform/gradle-testing-junit-platform@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-testing-jvm-7.1.1.jar": "pkg:maven/gradle-testing-jvm/gradle-testing-jvm@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-testing-native-7.1.1.jar": "pkg:maven/gradle-testing-native/gradle-testing-native@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-tooling-api-builders-7.1.1.jar": "pkg:maven/gradle-tooling-api-builders/gradle-tooling-api-builders@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-tooling-native-7.1.1.jar": "pkg:maven/gradle-tooling-native/gradle-tooling-native@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-version-control-7.1.1.jar": "pkg:maven/gradle-version-control/gradle-version-control@7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gradle-workers-7.1.1.jar": "pkg:maven/gradle-workers/gradle-workers@7.1.1",
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/jopenssl.jar": "pkg:maven/jopenssl/jopenssl",
|
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/jopenssl.jar": "pkg:maven/jopenssl/jopenssl",
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/json/ext/generator.jar": "pkg:maven/generator/generator",
|
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/jopenssl.jar:rubygems:jruby-openssl": "pkg:maven/rubygems/jruby-openssl@0.9.21",
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/json/ext/parser.jar": "pkg:maven/parser/parser",
|
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/json/ext/parser.jar": "pkg:maven/parser/parser",
|
||||||
|
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/json/ext/generator.jar": "pkg:maven/generator/generator",
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/psych.jar": "pkg:maven/psych/psych",
|
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/psych.jar": "pkg:maven/psych/psych",
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/racc/cparse-jruby.jar": "pkg:maven/cparse-jruby/cparse-jruby",
|
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/racc/cparse-jruby.jar": "pkg:maven/cparse-jruby/cparse-jruby",
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar": "pkg:maven/readline/readline",
|
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar": "pkg:maven/readline/readline",
|
||||||
@@ -51,8 +138,64 @@ var noAssertion = map[string]string{
|
|||||||
"/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar": "pkg:maven/sdk/sdk@3.0",
|
"/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar": "pkg:maven/sdk/sdk@3.0",
|
||||||
|
|
||||||
// syft generates incorrect purls
|
// syft generates incorrect purls
|
||||||
"/packages/akka-actor_2.13-2.6.6.jar": "pkg:maven/com.typesafe.akka/akka-actor_2.13@2.6.6",
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/jbcrypt-1.0.0.jar": "pkg:maven/org.connectbot/jbcrypt@1.0.0",
|
||||||
"/packages/akka-management-cluster-bootstrap_2.13-1.2.0.jar": "pkg:maven/com.lightbend.akka.management/akka-management-cluster-bootstrap_2.13@1.2.0",
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/tink-1.5.0.jar": "pkg:maven/com.google.crypto.tink/tink@1.5.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/fastutil-8.5.2-min.jar": "pkg:maven/it.unimi.dsi/fastutil@8.5.2-min",
|
||||||
|
"/packages/gradle-7.1.1/lib/file-events-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/file-events-linux-aarch64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-linux-aarch64@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/file-events-linux-amd64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-linux-amd64@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/file-events-osx-aarch64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-osx-aarch64@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/file-events-osx-amd64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-osx-amd64@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/file-events-windows-amd64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-windows-amd64@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/file-events-windows-amd64-min-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-windows-amd64-min@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/file-events-windows-i386-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-windows-i386@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/file-events-windows-i386-min-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/file-events-windows-i386-min@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/hamcrest-core-1.3.jar": "pkg:maven/org.hamcrest/hamcrest-core@1.3",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-compiler-embeddable-1.4.31-patched-for-gradle-7.1.1.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-compiler-embeddable@1.4.31-patched-for-gradle-7.1.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-daemon-embeddable-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-daemon-embeddable@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-reflect-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-reflect@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-sam-with-receiver-compiler-plugin-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-sam-with-receiver-compiler-plugin@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-script-runtime-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-script-runtime@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-scripting-common-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-scripting-common@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-scripting-compiler-embeddable-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-scripting-compiler-embeddable@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-scripting-compiler-impl-embeddable-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-scripting-compiler-impl-embeddable@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-scripting-jvm-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-scripting-jvm@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-scripting-jvm-host-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-scripting-jvm-host@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-stdlib-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-stdlib@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-stdlib-common-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-stdlib-common@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-stdlib-jdk7-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-stdlib-jdk7@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlin-stdlib-jdk8-1.4.31.jar": "pkg:maven/org.jetbrains.kotlin/kotlin-stdlib-jdk8@1.4.31",
|
||||||
|
"/packages/gradle-7.1.1/lib/kotlinx-metadata-jvm-0.2.0.jar": "pkg:maven/org.jetbrains.kotlinx/kotlinx-metadata-jvm@0.2.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-freebsd-amd64-libcpp-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-freebsd-amd64-libcpp@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-linux-aarch64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-linux-aarch64@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-linux-aarch64-ncurses5-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-linux-aarch64-ncurses5@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-linux-aarch64-ncurses6-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-linux-aarch64-ncurses6@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-linux-amd64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-linux-amd64@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-linux-amd64-ncurses5-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-linux-amd64-ncurses5@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-linux-amd64-ncurses6-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-linux-amd64-ncurses6@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-osx-aarch64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-osx-aarch64@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-osx-amd64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-osx-amd64@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-windows-amd64-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-windows-amd64@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-windows-amd64-min-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-windows-amd64-min@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-windows-i386-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-windows-i386@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/native-platform-windows-i386-min-0.22-milestone-16.jar": "pkg:maven/net.rubygrapefruit/native-platform-windows-i386-min@0.22-milestone-16",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/apiguardian-api-1.1.0.jar": "pkg:maven/org.apiguardian/apiguardian-api@1.1.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/bsh-2.0b6.jar": "pkg:maven/org.apache-extras.beanshell/bsh@2.0b6",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/google-api-client-1.25.0.jar": "pkg:maven/com.google.api-client/google-api-client@1.25.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/google-api-services-storage-v1-rev171-1.25.0.jar": "pkg:maven/com.google.apis/google-api-services-storage@v1-rev171-1.25.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jcommander-1.78.jar": "pkg:maven/com.beust/jcommander@1.78",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/junit-platform-commons-1.7.2.jar": "pkg:maven/org.junit.platform/junit-platform-commons@1.7.2",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/junit-platform-engine-1.7.2.jar": "pkg:maven/org.junit.platform/junit-platform-engine@1.7.2",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/junit-platform-launcher-1.7.2.jar": "pkg:maven/org.junit.platform/junit-platform-launcher@1.7.2",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/nekohtml-1.9.22.jar": "pkg:maven/net.sourceforge.nekohtml/nekohtml@1.9.22",
|
||||||
|
"/packages/gradle-7.1.1/lib/tomlj-1.0.0.jar": "pkg:maven/org.tomlj/tomlj@1.0.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/trove4j-1.0.20181211.jar": "pkg:maven/net.sf.trove4j /trove4j@1.0.20181211",
|
||||||
|
"/packages/gradle-7.1.1/lib/xml-apis-1.4.01.jar": "pkg:maven/xml-apis/xml-apis@1.4.01",
|
||||||
|
"/packages/gradle-7.1.1/lib/asm-analysis-9.1.jar": "pkg:maven/org.ow2.asm/asm-analysis@9.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/asm-commons-9.1.jar": "pkg:maven/org.ow2.asm/asm-commons@9.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/asm-tree-9.1.jar": "pkg:maven/org.ow2.asm/asm-tree@9.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/ivy-2.3.0.jar": "pkg:maven/org.apache.ivy/ivy@2.3.0",
|
||||||
"/packages/hudson.war:WEB-INF/lib/asm-2.2.3.jar": "pkg:maven/asm/asm@2.2.3",
|
"/packages/hudson.war:WEB-INF/lib/asm-2.2.3.jar": "pkg:maven/asm/asm@2.2.3",
|
||||||
"/packages/hudson.war:WEB-INF/lib/asm-commons-2.2.3.jar": "pkg:maven/asm/asm-commons@2.2.3",
|
"/packages/hudson.war:WEB-INF/lib/asm-commons-2.2.3.jar": "pkg:maven/asm/asm-commons@2.2.3",
|
||||||
"/packages/hudson.war:WEB-INF/lib/asm-tree-2.2.3.jar": "pkg:maven/asm/asm-tree@2.2.3",
|
"/packages/hudson.war:WEB-INF/lib/asm-tree-2.2.3.jar": "pkg:maven/asm/asm-tree@2.2.3",
|
||||||
@@ -61,9 +204,64 @@ var noAssertion = map[string]string{
|
|||||||
"/packages/hudson.war:WEB-INF/lib/xpp3-1.1.4c.jar": "pkg:maven/xpp3/xpp3@1.1.4c",
|
"/packages/hudson.war:WEB-INF/lib/xpp3-1.1.4c.jar": "pkg:maven/xpp3/xpp3@1.1.4c",
|
||||||
"/packages/hudson.war:WEB-INF/hudson-cli.jar": "pkg:maven/org.jvnet.hudson.main/hudson-cli@1.390",
|
"/packages/hudson.war:WEB-INF/hudson-cli.jar": "pkg:maven/org.jvnet.hudson.main/hudson-cli@1.390",
|
||||||
"/packages/hudson.war:WEB-INF/lib/dom4j-1.6.1-hudson-3.jar": "pkg:maven/org.jvnet.hudson.dom4j/dom4j@1.6.1-hudson-3",
|
"/packages/hudson.war:WEB-INF/lib/dom4j-1.6.1-hudson-3.jar": "pkg:maven/org.jvnet.hudson.dom4j/dom4j@1.6.1-hudson-3",
|
||||||
|
"/packages/newrelic-agent-8.8.0.jar": "pkg:maven/com.newrelic.bootstrap.BootstrapAgent/newrelic-agent@8.8.0",
|
||||||
|
"/packages/newrelic-agent-8.8.0.jar:agent-bridge-datastore.jar": "pkg:maven/agent-bridge-datastore/agent-bridge-datastore@8.8.0",
|
||||||
|
"/packages/newrelic-agent-8.8.0.jar:agent-bridge.jar": "pkg:maven/agent-bridge/agent-bridge@8.8.0",
|
||||||
|
"/packages/newrelic-agent-8.8.0.jar:newrelic-api.jar": "pkg:maven/newrelic-api/newrelic-api@8.8.0",
|
||||||
|
"/packages/newrelic-agent-8.8.0.jar:newrelic-security-agent.jar": "pkg:maven/newrelic-security-agent/newrelic-security-agent@1.0.7-public-preview",
|
||||||
|
"/packages/newrelic-agent-8.8.0.jar:newrelic-security-api.jar": "pkg:maven/newrelic-security-api/newrelic-security-api@1.0.7-public-preview",
|
||||||
|
"/packages/newrelic-agent-8.8.0.jar:newrelic-weaver-api.jar": "pkg:maven/newrelic-weaver-api/newrelic-weaver-api@8.8.0",
|
||||||
|
"/packages/newrelic-agent-8.8.0.jar:newrelic-weaver-scala-api.jar": "pkg:maven/newrelic-weaver-scala-api/newrelic-weaver-scala-api@8.8.0",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/jsr250-api-1.0.jar": "pkg:maven/javax.annotation/jsr250-api@1.0",
|
||||||
|
"/packages/TwilioNotifier.hpi:WEB-INF/lib/commons-httpclient-3.1.jar": "pkg:maven/commons-httpclient/commons-httpclient@3.1",
|
||||||
"/packages/xpp3_min-1.1.4c.jar": "pkg:maven/xpp3/xpp3_min@1.1.4c",
|
"/packages/xpp3_min-1.1.4c.jar": "pkg:maven/xpp3/xpp3_min@1.1.4c",
|
||||||
|
|
||||||
// syft generates an unstable purl
|
// Unclear: groupid might be org.glassfish.jaxb or com.sun.xml.bind
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jaxb-core-3.0.0.jar": "pkg:maven/org.glassfish.jaxb/jaxb-core@3.0.0",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructed by:
|
||||||
|
// syft anchore/test_images:java-1abc58f -o json | jq -r '.artifacts.[] | [.metadata.virtualPath, .purl, ""] | @csv' | grep 'pkg:maven' | sort | uniq >> /tmp/java_artifacts_mapping.txt
|
||||||
|
// The map was then hand-edited for correctness by comparing to Maven Central.
|
||||||
|
var expectedPURLs = map[string]string{
|
||||||
|
"/packages/activemq-client-5.18.2.jar": "pkg:maven/org.apache.activemq/activemq-client@5.18.2",
|
||||||
|
"/packages/activemq-protobuf-1.1.jar": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1",
|
||||||
|
"/packages/akka-actor_2.13-2.6.6.jar": "pkg:maven/com.typesafe.akka/akka-actor_2.13@2.6.6",
|
||||||
|
"/packages/akka-management-cluster-bootstrap_2.13-1.2.0.jar": "pkg:maven/com.lightbend.akka.management/akka-management-cluster-bootstrap_2.13@1.2.0",
|
||||||
|
"/packages/ant-1.10.3.jar": "pkg:maven/org.apache.ant/ant@1.10.3",
|
||||||
|
"/packages/apache-chainsaw-2.1.0.jar": "pkg:maven/log4j/apache-chainsaw@2.1.0",
|
||||||
|
"/packages/apache-log4j-extras-1.1.jar": "pkg:maven/log4j/apache-log4j-extras@1.1",
|
||||||
|
"/packages/apoc-4.4.0.11.jar": "pkg:maven/org.neo4j.procedure/apoc@4.4.0.11",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi": "pkg:maven/io.jenkins.plugins/atlassian-bitbucket-server-integration@2.1.2",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/atlassian-bitbucket-server-integration.jar": "pkg:maven/io.jenkins.plugins/atlassian-bitbucket-server-integration@2.1.2",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/commons-codec-1.13.jar": "pkg:maven/commons-codec/commons-codec@1.13",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/commons-lang3-3.9.jar": "pkg:maven/org.apache.commons/commons-lang3@3.9",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/eddsa-0.3.0.jar": "pkg:maven/net.i2p.crypto/eddsa@0.3.0",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/httpcore-4.4.9.jar": "pkg:maven/org.apache.httpcomponents/httpcore@4.4.9",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/jackson-annotations-2.11.2.jar": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.11.2",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/jackson-core-2.11.2.jar": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.11.2",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/jackson-databind-2.9.10.7.jar": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.9.10.7",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/jcommon-1.0.24.jar": "pkg:maven/org.jfree/jcommon@1.0.24",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/json-20180813.jar": "pkg:maven/org.json/json@20180813",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/oauth-20100527.jar": "pkg:maven/net.oauth.core/oauth@20100527",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/oauth-provider-20100527.jar": "pkg:maven/net.oauth.core/oauth-provider@20100527",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/okhttp-3.14.1.jar": "pkg:maven/com.squareup.okhttp3/okhttp@3.14.1",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/okio-1.17.2.jar": "pkg:maven/com.squareup.okio/okio@1.17.2",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/protobuf-java-3.11.1.jar": "pkg:maven/com.google.protobuf/protobuf-java@3.11.1",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/trilead-putty-extension-1.2.jar": "pkg:maven/org.kohsuke/trilead-putty-extension@1.2",
|
||||||
|
"/packages/atlassian-bitbucket-server-integration.hpi:WEB-INF/lib/trilead-ssh2-build-217-jenkins-27.jar:org.jenkins-ci:trilead-ssh2": "pkg:maven/org.jenkins-ci/trilead-ssh2@build-217-jenkins-27",
|
||||||
|
"/packages/aws-sam.hpi": "pkg:maven/io.jenkins.plugins/aws-sam@1.2.2",
|
||||||
|
"/packages/aws-sam.hpi:WEB-INF/lib/aws-sam.jar": "pkg:maven/io.jenkins.plugins/aws-sam@1.2.2",
|
||||||
|
"/packages/aws-sam.hpi:WEB-INF/lib/json-20180130.jar": "pkg:maven/org.json/json@20180130",
|
||||||
|
"/packages/aws-sam.hpi:WEB-INF/lib/snakeyaml-1.21.jar": "pkg:maven/org.yaml/snakeyaml@1.21",
|
||||||
|
"/packages/bc-fips-1.0.2.3.jar": "pkg:maven/org.bouncycastle/bc-fips@1.0.2.3",
|
||||||
|
"/packages/camel-core-3.1.0.jar": "pkg:maven/org.apache.camel/camel-core@3.1.0",
|
||||||
|
"/packages/cassandra-all-4.1.1.jar": "pkg:maven/org.apache.cassandra/cassandra-all@4.1.1",
|
||||||
|
"/packages/commons-logging-1.1.1.jar": "pkg:maven/commons-logging/commons-logging@1.1.1",
|
||||||
|
"/packages/commons-vfs-1.0.jar": "pkg:maven/commons-vfs/commons-vfs@1.0",
|
||||||
|
"/packages/cxf-rt-transports-http-2.7.3.jar": "pkg:maven/org.apache.cxf/cxf-rt-transports-http@2.7.3",
|
||||||
|
"/packages/dubbo-3.1.4.jar": "pkg:maven/org.apache.dubbo/dubbo@3.1.4",
|
||||||
|
"/packages/dubbo-3.1.4.jar:com.alibaba:hessian-lite": "pkg:maven/com.alibaba/hessian-lite@3.2.13",
|
||||||
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-auth": "pkg:maven/org.apache.dubbo/dubbo-auth@3.1.4",
|
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-auth": "pkg:maven/org.apache.dubbo/dubbo-auth@3.1.4",
|
||||||
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-cluster": "pkg:maven/org.apache.dubbo/dubbo-cluster@3.1.4",
|
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-cluster": "pkg:maven/org.apache.dubbo/dubbo-cluster@3.1.4",
|
||||||
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-common": "pkg:maven/org.apache.dubbo/dubbo-common@3.1.4",
|
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-common": "pkg:maven/org.apache.dubbo/dubbo-common@3.1.4",
|
||||||
@@ -111,89 +309,123 @@ var noAssertion = map[string]string{
|
|||||||
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-hessian2": "pkg:maven/org.apache.dubbo/dubbo-serialization-hessian2@3.1.4",
|
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-hessian2": "pkg:maven/org.apache.dubbo/dubbo-serialization-hessian2@3.1.4",
|
||||||
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-jdk": "pkg:maven/org.apache.dubbo/dubbo-serialization-jdk@3.1.4",
|
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-jdk": "pkg:maven/org.apache.dubbo/dubbo-serialization-jdk@3.1.4",
|
||||||
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-xds": "pkg:maven/org.apache.dubbo/dubbo-xds@3.1.4",
|
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-xds": "pkg:maven/org.apache.dubbo/dubbo-xds@3.1.4",
|
||||||
"/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo": "pkg:maven/org.apache.dubbo/dubbo@3.1.4",
|
|
||||||
"/packages/dubbo-3.1.4.jar": "pkg:maven/org.apache.dubbo/dubbo@3.1.4",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructed by:
|
|
||||||
// syft anchore/test_images:java-1abc58f -o json | jq -r '.artifacts.[] | [.metadata.virtualPath, .purl, ""] | @csv' | grep 'pkg:maven' | sort | uniq >> /tmp/java_artifacts_mapping.txt
|
|
||||||
// The map was then hand-edited for correctness by comparing to Maven Central.
|
|
||||||
var expectedPURLs = map[string]string{
|
|
||||||
"/packages/activemq-client-5.18.2.jar": "pkg:maven/org.apache.activemq/activemq-client@5.18.2",
|
|
||||||
"/packages/activemq-protobuf-1.1.jar": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1",
|
|
||||||
// "/packages/akka-actor_2.13-2.6.6.jar": "pkg:maven/com.typesafe.akka/akka-actor_2.13@2.6.6",
|
|
||||||
// "/packages/akka-management-cluster-bootstrap_2.13-1.2.0.jar": "pkg:maven/com.lightbend.akka.management/akka-management-cluster-bootstrap_2.13@1.2.0",
|
|
||||||
"/packages/ant-1.10.3.jar": "pkg:maven/org.apache.ant/ant@1.10.3",
|
|
||||||
"/packages/apache-chainsaw-2.1.0.jar": "pkg:maven/log4j/apache-chainsaw@2.1.0",
|
|
||||||
"/packages/apache-log4j-extras-1.1.jar": "pkg:maven/log4j/apache-log4j-extras@1.1",
|
|
||||||
"/packages/apoc-4.4.0.11.jar": "pkg:maven/org.neo4j.procedure/apoc@4.4.0.11",
|
|
||||||
"/packages/bc-fips-1.0.2.3.jar": "pkg:maven/org.bouncycastle/bc-fips@1.0.2.3",
|
|
||||||
"/packages/camel-core-3.1.0.jar": "pkg:maven/org.apache.camel/camel-core@3.1.0",
|
|
||||||
"/packages/cassandra-all-4.1.1.jar": "pkg:maven/org.apache.cassandra/cassandra-all@4.1.1",
|
|
||||||
"/packages/commons-logging-1.1.1.jar": "pkg:maven/commons-logging/commons-logging@1.1.1",
|
|
||||||
"/packages/commons-vfs-1.0.jar": "pkg:maven/commons-vfs/commons-vfs@1.0",
|
|
||||||
"/packages/cxf-rt-transports-http-2.7.3.jar": "pkg:maven/org.apache.cxf/cxf-rt-transports-http@2.7.3",
|
|
||||||
"/packages/dubbo-3.1.4.jar:com.alibaba:hessian-lite": "pkg:maven/com.alibaba/hessian-lite@3.2.13",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-auth": "pkg:maven/org.apache.dubbo/dubbo-auth@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-cluster": "pkg:maven/org.apache.dubbo/dubbo-cluster@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-common": "pkg:maven/org.apache.dubbo/dubbo-common@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-compatible": "pkg:maven/org.apache.dubbo/dubbo-compatible@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-config-api": "pkg:maven/org.apache.dubbo/dubbo-config-api@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-config-spring": "pkg:maven/org.apache.dubbo/dubbo-config-spring@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-apollo": "pkg:maven/org.apache.dubbo/dubbo-configcenter-apollo@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-nacos": "pkg:maven/org.apache.dubbo/dubbo-configcenter-nacos@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-configcenter-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-configcenter-zookeeper@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-container-api": "pkg:maven/org.apache.dubbo/dubbo-container-api@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-container-spring": "pkg:maven/org.apache.dubbo/dubbo-container-spring@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-filter-cache": "pkg:maven/org.apache.dubbo/dubbo-filter-cache@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-filter-validation": "pkg:maven/org.apache.dubbo/dubbo-filter-validation@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-kubernetes": "pkg:maven/org.apache.dubbo/dubbo-kubernetes@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-api": "pkg:maven/org.apache.dubbo/dubbo-metadata-api@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-definition-protobuf": "pkg:maven/org.apache.dubbo/dubbo-metadata-definition-protobuf@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-nacos": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-nacos@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-redis": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-redis@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metadata-report-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-metadata-report-zookeeper@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metrics-api": "pkg:maven/org.apache.dubbo/dubbo-metrics-api@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-metrics-prometheus": "pkg:maven/org.apache.dubbo/dubbo-metrics-prometheus@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-monitor-api": "pkg:maven/org.apache.dubbo/dubbo-monitor-api@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-monitor-default": "pkg:maven/org.apache.dubbo/dubbo-monitor-default@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-qos": "pkg:maven/org.apache.dubbo/dubbo-qos@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-reactive": "pkg:maven/org.apache.dubbo/dubbo-reactive@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-api": "pkg:maven/org.apache.dubbo/dubbo-registry-api@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-multicast": "pkg:maven/org.apache.dubbo/dubbo-registry-multicast@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-multiple": "pkg:maven/org.apache.dubbo/dubbo-registry-multiple@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-nacos": "pkg:maven/org.apache.dubbo/dubbo-registry-nacos@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-registry-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-registry-zookeeper@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-api": "pkg:maven/org.apache.dubbo/dubbo-remoting-api@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-http": "pkg:maven/org.apache.dubbo/dubbo-remoting-http@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-netty": "pkg:maven/org.apache.dubbo/dubbo-remoting-netty@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-netty4": "pkg:maven/org.apache.dubbo/dubbo-remoting-netty4@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-zookeeper": "pkg:maven/org.apache.dubbo/dubbo-remoting-zookeeper@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-remoting-zookeeper-curator5": "pkg:maven/org.apache.dubbo/dubbo-remoting-zookeeper-curator5@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-api": "pkg:maven/org.apache.dubbo/dubbo-rpc-api@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-dubbo": "pkg:maven/org.apache.dubbo/dubbo-rpc-dubbo@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-grpc": "pkg:maven/org.apache.dubbo/dubbo-rpc-grpc@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-injvm": "pkg:maven/org.apache.dubbo/dubbo-rpc-injvm@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-rest": "pkg:maven/org.apache.dubbo/dubbo-rpc-rest@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-rpc-triple": "pkg:maven/org.apache.dubbo/dubbo-rpc-triple@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-api": "pkg:maven/org.apache.dubbo/dubbo-serialization-api@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-fastjson2": "pkg:maven/org.apache.dubbo/dubbo-serialization-fastjson2@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-hessian2": "pkg:maven/org.apache.dubbo/dubbo-serialization-hessian2@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-serialization-jdk": "pkg:maven/org.apache.dubbo/dubbo-serialization-jdk@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo-xds": "pkg:maven/org.apache.dubbo/dubbo-xds@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar:org.apache.dubbo:dubbo": "pkg:maven/org.apache.dubbo/dubbo@3.1.4",
|
|
||||||
// "/packages/dubbo-3.1.4.jar": "pkg:maven/org.apache.dubbo/dubbo@3.1.4",
|
|
||||||
"/packages/elasticsearch-8.10.2.jar": "pkg:maven/org.elasticsearch/elasticsearch@8.10.2",
|
"/packages/elasticsearch-8.10.2.jar": "pkg:maven/org.elasticsearch/elasticsearch@8.10.2",
|
||||||
"/packages/elasticsearch-rest-client-sniffer-7.17.11.jar": "pkg:maven/org.elasticsearch.client/elasticsearch-rest-client-sniffer@7.17.11",
|
"/packages/elasticsearch-rest-client-sniffer-7.17.11.jar": "pkg:maven/org.elasticsearch.client/elasticsearch-rest-client-sniffer@7.17.11",
|
||||||
"/packages/example-java-app-gradle-0.1.0.ear": "pkg:maven/example-java-app-gradle/example-java-app-gradle@0.1.0",
|
"/packages/example-java-app-gradle-0.1.0.ear": "pkg:maven/example-java-app-gradle/example-java-app-gradle@0.1.0",
|
||||||
|
"/packages/generic-webhook-trigger.hpi": "pkg:maven/org.jenkins-ci.plugins/generic-webhook-trigger@1.71",
|
||||||
|
"/packages/generic-webhook-trigger.hpi:WEB-INF/lib/accessors-smart-1.2.jar": "pkg:maven/net.minidev/accessors-smart@1.2",
|
||||||
|
"/packages/generic-webhook-trigger.hpi:WEB-INF/lib/asm-5.0.4.jar": "pkg:maven/org.objectweb.asm/asm@5.0.4",
|
||||||
|
"/packages/generic-webhook-trigger.hpi:WEB-INF/lib/commons-ip-math-1.32.jar": "pkg:maven/com.github.jgonian/commons-ip-math@1.32",
|
||||||
|
"/packages/generic-webhook-trigger.hpi:WEB-INF/lib/generic-webhook-trigger.jar": "pkg:maven/org.jenkins-ci.plugins/generic-webhook-trigger@1.71",
|
||||||
|
"/packages/generic-webhook-trigger.hpi:WEB-INF/lib/gson-2.8.2.jar": "pkg:maven/com.google.code.gson/gson@2.8.2",
|
||||||
|
"/packages/generic-webhook-trigger.hpi:WEB-INF/lib/json-path-2.3.0.jar": "pkg:maven/com.jayway.jsonpath.json-path/json-path@2.3.0",
|
||||||
|
"/packages/generic-webhook-trigger.hpi:WEB-INF/lib/json-smart-2.3.jar": "pkg:maven/net.minidev/json-smart@2.3",
|
||||||
"/packages/geode-core-1.14.3.jar": "pkg:maven/org.apache.geode/geode-core@1.14.3",
|
"/packages/geode-core-1.14.3.jar": "pkg:maven/org.apache.geode/geode-core@1.14.3",
|
||||||
"/packages/github-api-1.118.jar": "pkg:maven/org.kohsuke/github-api@1.118",
|
"/packages/github-api-1.118.jar": "pkg:maven/org.kohsuke/github-api@1.118",
|
||||||
"/packages/google-oauth-client-1.25.0.jar": "pkg:maven/com.google.oauth-client/google-oauth-client@1.25.0",
|
"/packages/google-oauth-client-1.25.0.jar": "pkg:maven/com.google.oauth-client/google-oauth-client@1.25.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/annotations-20.1.0.jar": "pkg:maven/org.jetbrains.annotations/annotations@20.1.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/ant-1.10.9.jar": "pkg:maven/org.apache.ant/ant@1.10.9",
|
||||||
|
"/packages/gradle-7.1.1/lib/ant-antlr-1.10.9.jar": "pkg:maven/org.apache.ant/ant-antlr@1.10.9",
|
||||||
|
"/packages/gradle-7.1.1/lib/ant-junit-1.10.9.jar": "pkg:maven/org.apache.ant/ant-junit@1.10.9",
|
||||||
|
"/packages/gradle-7.1.1/lib/ant-launcher-1.10.9.jar": "pkg:maven/org.apache.ant/ant-launcher@1.10.9",
|
||||||
|
"/packages/gradle-7.1.1/lib/antlr4-runtime-4.7.2.jar": "pkg:maven/org.antlr/antlr4-runtime@4.7.2",
|
||||||
|
"/packages/gradle-7.1.1/lib/asm-9.1.jar": "pkg:maven/org.objectweb.asm/asm@9.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/commons-compress-1.20.jar": "pkg:maven/org.apache.commons/commons-compress@1.20",
|
||||||
|
"/packages/gradle-7.1.1/lib/commons-io-2.6.jar": "pkg:maven/commons-io/commons-io@2.6",
|
||||||
|
"/packages/gradle-7.1.1/lib/commons-lang-2.6.jar": "pkg:maven/commons-lang/commons-lang@2.6",
|
||||||
|
"/packages/gradle-7.1.1/lib/failureaccess-1.0.1.jar": "pkg:maven/com.google.guava/failureaccess@1.0.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-ant-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-ant@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-astbuilder-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-astbuilder@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-console-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-console@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-datetime-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-datetime@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-dateutil-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-dateutil@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-docgenerator-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-docgenerator@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-groovydoc-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-groovydoc@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-json-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-json@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-nio-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-nio@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-sql-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-sql@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-swing-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-swing@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-templates-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-templates@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-test-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-test@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/groovy-xml-3.0.7.jar": "pkg:maven/org.codehaus.groovy/groovy-xml@3.0.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/guava-27.1-android.jar": "pkg:maven/com.google.guava/guava@27.1-android",
|
||||||
|
"/packages/gradle-7.1.1/lib/jansi-1.18.jar": "pkg:maven/org.fusesource.jansi/jansi@1.18",
|
||||||
|
"/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.hawtjni:hawtjni-runtime": "pkg:maven/org.fusesource.hawtjni/hawtjni-runtime@1.17",
|
||||||
|
"/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-freebsd32": "pkg:maven/org.fusesource.jansi/jansi-freebsd32@1.8",
|
||||||
|
"/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-freebsd64": "pkg:maven/org.fusesource.jansi/jansi-freebsd64@1.8",
|
||||||
|
"/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-linux32": "pkg:maven/org.fusesource.jansi/jansi-linux32@1.8",
|
||||||
|
"/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-linux64": "pkg:maven/org.fusesource.jansi/jansi-linux64@1.8",
|
||||||
|
"/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-native": "pkg:maven/org.fusesource.jansi/jansi-native@1.8",
|
||||||
|
"/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-osx": "pkg:maven/org.fusesource.jansi/jansi-osx@1.8",
|
||||||
|
"/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-windows32": "pkg:maven/org.fusesource.jansi/jansi-windows32@1.8",
|
||||||
|
"/packages/gradle-7.1.1/lib/jansi-1.18.jar:org.fusesource.jansi:jansi-windows64": "pkg:maven/org.fusesource.jansi/jansi-windows64@1.8",
|
||||||
|
"/packages/gradle-7.1.1/lib/javaparser-core-3.17.0.jar": "pkg:maven/com.github.javaparser/javaparser-core@3.17.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/jcl-over-slf4j-1.7.30.jar": "pkg:maven/org.slf4j/jcl-over-slf4j@1.7.30",
|
||||||
|
"/packages/gradle-7.1.1/lib/jsr305-3.0.2.jar": "pkg:maven/com.google.code.findbugs/jsr305@3.0.2",
|
||||||
|
"/packages/gradle-7.1.1/lib/jul-to-slf4j-1.7.30.jar": "pkg:maven/org.slf4j/jul-to-slf4j@1.7.30",
|
||||||
|
"/packages/gradle-7.1.1/lib/junit-4.13.2.jar": "pkg:maven/junit/junit@4.13.2",
|
||||||
|
"/packages/gradle-7.1.1/lib/kryo-2.24.0.jar": "pkg:maven/com.esotericsoftware.kryo/kryo@2.24.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/kryo-2.24.0.jar:com.esotericsoftware.reflectasm:reflectasm": "pkg:maven/com.esotericsoftware.reflectasm/reflectasm@1.09",
|
||||||
|
"/packages/gradle-7.1.1/lib/log4j-over-slf4j-1.7.30.jar": "pkg:maven/org.slf4j/log4j-over-slf4j@1.7.30",
|
||||||
|
"/packages/gradle-7.1.1/lib/minlog-1.2.jar": "pkg:maven/com.esotericsoftware.minlog/minlog@1.2",
|
||||||
|
"/packages/gradle-7.1.1/lib/objenesis-2.6.jar": "pkg:maven/org.objenesis/objenesis@2.6",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/aws-java-sdk-core-1.11.948.jar": "pkg:maven/com.amazonaws/aws-java-sdk-core@1.11.948",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/aws-java-sdk-kms-1.11.948.jar": "pkg:maven/com.amazonaws/aws-java-sdk-kms@1.11.948",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/aws-java-sdk-s3-1.11.948.jar": "pkg:maven/com.amazonaws/aws-java-sdk-s3@1.11.948",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/aws-java-sdk-sts-1.11.948.jar": "pkg:maven/com.amazonaws/aws-java-sdk-sts@1.11.948",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/bcpg-jdk15on-1.68.jar": "pkg:maven/org.bouncycastle/bcpg-jdk15on@1.68",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/bcpkix-jdk15on-1.68.jar": "pkg:maven/org.bouncycastle/bcpkix-jdk15on@1.68",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/bcprov-jdk15on-1.68.jar": "pkg:maven/org.bouncycastle/bcprov-jdk15on@1.68",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/commons-codec-1.15.jar": "pkg:maven/commons-codec/commons-codec@1.15",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/dd-plist-1.21.jar": "pkg:maven/com.googlecode.plist/dd-plist@1.21",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/google-api-services-storage-v1-rev171-1.25.0.jar:com.google.apis:google-api-services-storage": "pkg:maven/com.google.apis/google-api-services-storage@v1-rev171-1.25.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/google-http-client-1.25.0.jar": "pkg:maven/com.google.http-client/google-http-client@1.25.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/google-http-client-jackson2-1.25.0.jar": "pkg:maven/com.google.http-client/google-http-client-jackson2@1.25.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/google-oauth-client-1.25.0.jar": "pkg:maven/com.google.oauth-client/google-oauth-client@1.25.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/gson-2.8.6.jar": "pkg:maven/com.google.code.gson/gson@2.8.6",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/httpclient-4.5.13.jar": "pkg:maven/org.apache.httpcomponents/httpclient@4.5.13",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/httpcore-4.4.14.jar": "pkg:maven/org.apache.httpcomponents/httpcore@4.4.14",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/ion-java-1.0.2.jar": "pkg:maven/software.amazon.ion/ion-java@1.0.2",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jackson-annotations-2.12.1.jar": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.12.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jackson-core-2.12.1.jar": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.12.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jackson-databind-2.12.1.jar": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.12.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jakarta.activation-2.0.0.jar": "pkg:maven/com.sun.activation/jakarta.activation@2.0.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jakarta.xml.bind-api-3.0.0.jar": "pkg:maven/jakarta.xml.bind/jakarta.xml.bind-api@3.0.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jatl-0.2.3.jar": "pkg:maven/com.googlecode.jatl/jatl@0.2.3",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jaxb-core-3.0.0.jar:com.sun.istack:istack-commons-runtime": "pkg:maven/com.sun.istack/istack-commons-runtime@4.0.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jaxb-core-3.0.0.jar:org.glassfish.jaxb:txw2": "pkg:maven/org.glassfish.jaxb/txw2@3.0.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jaxb-impl-3.0.0.jar": "pkg:maven/com.sun.xml.bind/jaxb-impl@3.0.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jaxb-impl-3.0.0.jar:org.glassfish.jaxb:jaxb-runtime": "pkg:maven/org.glassfish.jaxb/jaxb-runtime@3.0.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jcifs-1.3.17.jar": "pkg:maven/jcifs/jcifs@1.3.17",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jmespath-java-1.11.948.jar": "pkg:maven/com.amazonaws/jmespath-java@1.11.948",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/joda-time-2.10.4.jar": "pkg:maven/joda-time/joda-time@2.10.4",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jsch-0.1.55.jar": "pkg:maven/com.jcraft/jsch@0.1.55",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/jzlib-1.1.3.jar": "pkg:maven/com.jcraft/jzlib@1.1.3",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/maven-builder-support-3.6.3.jar": "pkg:maven/org.apache.maven/maven-builder-support@3.6.3",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/maven-model-3.6.3.jar": "pkg:maven/org.apache.maven/maven-model@3.6.3",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/maven-repository-metadata-3.6.3.jar": "pkg:maven/org.apache.maven/maven-repository-metadata@3.6.3",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/maven-settings-3.6.3.jar": "pkg:maven/org.apache.maven/maven-settings@3.6.3",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/maven-settings-builder-3.6.3.jar": "pkg:maven/org.apache.maven/maven-settings-builder@3.6.3",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/opentest4j-1.2.0.jar": "pkg:maven/org.opentest4j/opentest4j@1.2.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/org.eclipse.jgit-5.7.0.202003110725-r.jar": "pkg:maven/org.eclipse.jgit/org.eclipse.jgit@5.7.0.202003110725-r",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/plexus-cipher-1.7.jar": "pkg:maven/org.sonatype.plexus/plexus-cipher@1.7",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/plexus-interpolation-1.26.jar": "pkg:maven/org.codehaus.plexus/plexus-interpolation@1.26",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/plexus-sec-dispatcher-1.4.jar": "pkg:maven/org.sonatype.plexus/plexus-sec-dispatcher@1.4",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/plexus-utils-3.3.0.jar": "pkg:maven/org.codehaus.plexus/plexus-utils@3.3.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/snakeyaml-1.28.jar": "pkg:maven/org.yaml/snakeyaml@1.28",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/testng-6.3.1.jar": "pkg:maven/org.testng/testng@6.3.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/plugins/xercesImpl-2.12.0.jar": "pkg:maven/org.apache.xerces.impl.Version/xercesImpl@2.12.0",
|
||||||
|
"/packages/gradle-7.1.1/lib/qdox-1.12.1.jar": "pkg:maven/com.thoughtworks.qdox/qdox@1.12.1",
|
||||||
|
"/packages/gradle-7.1.1/lib/slf4j-api-1.7.30.jar": "pkg:maven/org.slf4j/slf4j-api@1.7.30",
|
||||||
|
"/packages/gradle.hpi": "pkg:maven/org.jenkins-ci.plugins/gradle@1.36",
|
||||||
|
"/packages/gradle.hpi:WEB-INF/lib/gradle-plugin-1.36.jar": "pkg:maven/org.jenkins-ci.plugins/gradle-plugin@1.36",
|
||||||
|
"/packages/graphql-java-20.0.jar": "pkg:maven/com.graphql-java/graphql-java@20.0",
|
||||||
"/packages/graphql-java-20.0.jar:com.google.guava:guava": "pkg:maven/com.google.guava/guava@31.0.1-jre",
|
"/packages/graphql-java-20.0.jar:com.google.guava:guava": "pkg:maven/com.google.guava/guava@31.0.1-jre",
|
||||||
"/packages/graphql-java-20.0.jar:org.antlr:antlr4-runtime": "pkg:maven/org.antlr/antlr4-runtime@4.9.3",
|
"/packages/graphql-java-20.0.jar:org.antlr:antlr4-runtime": "pkg:maven/org.antlr/antlr4-runtime@4.9.3",
|
||||||
"/packages/graphql-java-20.0.jar": "pkg:maven/com.graphql-java/graphql-java@20.0",
|
|
||||||
"/packages/guava-29.0-jre.jar": "pkg:maven/com.google.guava/guava@29.0-jre",
|
"/packages/guava-29.0-jre.jar": "pkg:maven/com.google.guava/guava@29.0-jre",
|
||||||
"/packages/hadoop-common-3.3.2.jar": "pkg:maven/org.apache.hadoop/hadoop-common@3.3.2",
|
"/packages/hadoop-common-3.3.2.jar": "pkg:maven/org.apache.hadoop/hadoop-common@3.3.2",
|
||||||
|
"/packages/hazelcast-5.2.4.jar": "pkg:maven/com.hazelcast/hazelcast@5.2.4",
|
||||||
"/packages/hazelcast-5.2.4.jar:com.fasterxml.jackson.core:jackson-core": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.15.2",
|
"/packages/hazelcast-5.2.4.jar:com.fasterxml.jackson.core:jackson-core": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.15.2",
|
||||||
"/packages/hazelcast-5.2.4.jar:com.fasterxml.jackson.jr:jackson-jr-annotation-support": "pkg:maven/com.fasterxml.jackson.jr/jackson-jr-annotation-support@2.15.2",
|
"/packages/hazelcast-5.2.4.jar:com.fasterxml.jackson.jr:jackson-jr-annotation-support": "pkg:maven/com.fasterxml.jackson.jr/jackson-jr-annotation-support@2.15.2",
|
||||||
"/packages/hazelcast-5.2.4.jar:com.fasterxml.jackson.jr:jackson-jr-objects": "pkg:maven/com.fasterxml.jackson.jr/jackson-jr-objects@2.15.2",
|
"/packages/hazelcast-5.2.4.jar:com.fasterxml.jackson.jr:jackson-jr-objects": "pkg:maven/com.fasterxml.jackson.jr/jackson-jr-objects@2.15.2",
|
||||||
@@ -202,7 +434,6 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/hazelcast-5.2.4.jar:io.github.classgraph:classgraph": "pkg:maven/io.github.classgraph/classgraph@4.8.149",
|
"/packages/hazelcast-5.2.4.jar:io.github.classgraph:classgraph": "pkg:maven/io.github.classgraph/classgraph@4.8.149",
|
||||||
"/packages/hazelcast-5.2.4.jar:org.json:json": "pkg:maven/org.json/json@20230227",
|
"/packages/hazelcast-5.2.4.jar:org.json:json": "pkg:maven/org.json/json@20230227",
|
||||||
"/packages/hazelcast-5.2.4.jar:org.snakeyaml:snakeyaml-engine": "pkg:maven/org.snakeyaml/snakeyaml-engine@2.3",
|
"/packages/hazelcast-5.2.4.jar:org.snakeyaml:snakeyaml-engine": "pkg:maven/org.snakeyaml/snakeyaml-engine@2.3",
|
||||||
"/packages/hazelcast-5.2.4.jar": "pkg:maven/com.hazelcast/hazelcast@5.2.4",
|
|
||||||
"/packages/hibernate-validator-6.1.3.Final.jar": "pkg:maven/org.hibernate.validator/hibernate-validator@6.1.3.Final",
|
"/packages/hibernate-validator-6.1.3.Final.jar": "pkg:maven/org.hibernate.validator/hibernate-validator@6.1.3.Final",
|
||||||
"/packages/http2-common-11.0.16.jar": "pkg:maven/org.eclipse.jetty.http2/http2-common@11.0.16",
|
"/packages/http2-common-11.0.16.jar": "pkg:maven/org.eclipse.jetty.http2/http2-common@11.0.16",
|
||||||
"/packages/hudson.war:WEB-INF/hudson-cli.jar:args4j:args4j": "pkg:maven/args4j/args4j@2.0.16",
|
"/packages/hudson.war:WEB-INF/hudson-cli.jar:args4j:args4j": "pkg:maven/args4j/args4j@2.0.16",
|
||||||
@@ -359,29 +590,105 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/jetty-server-12.0.0.alpha3.jar": "pkg:maven/org.eclipse.jetty/jetty-server@12.0.0.alpha3",
|
"/packages/jetty-server-12.0.0.alpha3.jar": "pkg:maven/org.eclipse.jetty/jetty-server@12.0.0.alpha3",
|
||||||
"/packages/jetty-setuid-java-1.0.4.jar": "pkg:maven/org.eclipse.jetty.toolchain.setuid/jetty-setuid-java@1.0.4",
|
"/packages/jetty-setuid-java-1.0.4.jar": "pkg:maven/org.eclipse.jetty.toolchain.setuid/jetty-setuid-java@1.0.4",
|
||||||
"/packages/jmdns-3.4.1.jar": "pkg:maven/javax.jmdns/jmdns@3.4.1",
|
"/packages/jmdns-3.4.1.jar": "pkg:maven/javax.jmdns/jmdns@3.4.1",
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/jopenssl.jar:rubygems:jruby-openssl": "pkg:maven/rubygems/jruby-openssl@0.9.21",
|
"/packages/jruby-stdlib-9.1.15.0.jar": "pkg:maven/org.jruby/jruby-stdlib@9.1.15.0",
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/org/bouncycastle/bcpkix-jdk15on/1.56/bcpkix-jdk15on-1.56.jar": "pkg:maven/org.bouncycastle/bcpkix-jdk15on@1.56",
|
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/org/bouncycastle/bcpkix-jdk15on/1.56/bcpkix-jdk15on-1.56.jar": "pkg:maven/org.bouncycastle/bcpkix-jdk15on@1.56",
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/org/bouncycastle/bcprov-jdk15on/1.56/bcprov-jdk15on-1.56.jar": "pkg:maven/org.bouncycastle/bcprov-jdk15on@1.56",
|
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/org/bouncycastle/bcprov-jdk15on/1.56/bcprov-jdk15on-1.56.jar": "pkg:maven/org.bouncycastle/bcprov-jdk15on@1.56",
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/org/yaml/snakeyaml/1.18/snakeyaml-1.18.jar": "pkg:maven/org.yaml/snakeyaml@1.18",
|
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/org/yaml/snakeyaml/1.18/snakeyaml-1.18.jar": "pkg:maven/org.yaml/snakeyaml@1.18",
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar:jline:jline": "pkg:maven/jline/jline@2.11",
|
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar:rubygems:jruby-readline": "pkg:maven/rubygems/jruby-readline@1.2.0",
|
|
||||||
"/packages/jruby-stdlib-9.1.15.0.jar": "pkg:maven/org.jruby/jruby-stdlib@9.1.15.0",
|
|
||||||
"/packages/jsch-0.1.55.jar": "pkg:maven/com.jcraft/jsch@0.1.55",
|
"/packages/jsch-0.1.55.jar": "pkg:maven/com.jcraft/jsch@0.1.55",
|
||||||
"/packages/junit-4.13.1.jar": "pkg:maven/junit/junit@4.13.1",
|
"/packages/junit-4.13.1.jar": "pkg:maven/junit/junit@4.13.1",
|
||||||
|
"/packages/junit.hpi": "pkg:maven/org.jenkins-ci.plugins/junit@1.25",
|
||||||
|
"/packages/junit.hpi:WEB-INF/lib/junit.jar": "pkg:maven/org.jenkins-ci.plugins/junit@1.25",
|
||||||
"/packages/kafka_2.13-3.2.2.jar": "pkg:maven/org.apache.kafka/kafka_2.13@3.2.2",
|
"/packages/kafka_2.13-3.2.2.jar": "pkg:maven/org.apache.kafka/kafka_2.13@3.2.2",
|
||||||
"/packages/keycloak-core-22.0.2.jar": "pkg:maven/org.keycloak/keycloak-core@22.0.2",
|
"/packages/keycloak-core-22.0.2.jar": "pkg:maven/org.keycloak/keycloak-core@22.0.2",
|
||||||
"/packages/log4j-1.2.16.jar": "pkg:maven/log4j/log4j@1.2.16",
|
"/packages/log4j-1.2.16.jar": "pkg:maven/log4j/log4j@1.2.16",
|
||||||
"/packages/log4j-core-2.17.0.jar": "pkg:maven/org.apache.logging.log4j/log4j-core@2.17.0",
|
"/packages/log4j-core-2.17.0.jar": "pkg:maven/org.apache.logging.log4j/log4j-core@2.17.0",
|
||||||
"/packages/log4j-over-slf4j-1.7.36.jar": "pkg:maven/org.slf4j/log4j-over-slf4j@1.7.36",
|
"/packages/log4j-over-slf4j-1.7.36.jar": "pkg:maven/org.slf4j/log4j-over-slf4j@1.7.36",
|
||||||
"/packages/manager-pojo-1.8.0.jar": "pkg:maven/org.apache.inlong/manager-pojo@1.8.0",
|
"/packages/manager-pojo-1.8.0.jar": "pkg:maven/org.apache.inlong/manager-pojo@1.8.0",
|
||||||
|
"/packages/maven-plugin.hpi": "pkg:maven/org.jenkins-ci.main/maven-plugin@3.10.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/annotations-3.0.1.jar": "pkg:maven/com.google.code.findbugs/annotations@3.0.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/annotations-3.0.1.jar:com.google.code.findbugs:jsr305": "pkg:maven/com.google.code.findbugs/jsr305@3.0.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/cdi-api-1.0.jar": "pkg:maven/javax.enterprise/cdi-api@1.0",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/commons-cli-1.4.jar": "pkg:maven/commons-cli/commons-cli@1.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/commons-lang3-3.11.jar": "pkg:maven/org.apache.commons/commons-lang3@3.11",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/commons-net-3.6.jar": "pkg:maven/commons-net/commons-net@3.6",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/doxia-sink-api-1.0.jar": "pkg:maven/org.apache.maven.doxia/doxia-sink-api@1.0",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/jackrabbit-webdav-2.14.4.jar": "pkg:maven/org.apache.jackrabbit/jackrabbit-webdav@2.14.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/jcl-over-slf4j-1.7.30.jar": "pkg:maven/org.slf4j/jcl-over-slf4j@1.7.30",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/jna-platform-4.1.0.jar": "pkg:maven/com.sun.jna.platform/jna-platform@4.1.0",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.connector-factory-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.connector-factory@0.0.9",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.core-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.core@0.0.9",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.jsch-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.jsch@0.0.9",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.pageant-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.pageant@0.0.9",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.sshagent-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.sshagent@0.0.9",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.usocket-jna-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.usocket-jna@0.0.9",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/jsch.agentproxy.usocket-nc-0.0.9.jar": "pkg:maven/com.jcraft/jsch.agentproxy.usocket-nc@0.0.9",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/jsoup-1.12.1.jar": "pkg:maven/org.jsoup/jsoup@1.12.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/lib-jenkins-maven-artifact-manager-1.2.jar": "pkg:maven/org.jenkins-ci.lib/lib-jenkins-maven-artifact-manager@1.2",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/lib-jenkins-maven-embedder-3.15.jar": "pkg:maven/org.jenkins-ci.lib/lib-jenkins-maven-embedder@3.15",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-agent-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven-agent@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-artifact-3.5.4.jar": "pkg:maven/org.apache.maven/maven-artifact@3.5.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-builder-support-3.5.4.jar": "pkg:maven/org.apache.maven/maven-builder-support@3.5.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-compat-3.5.4.jar": "pkg:maven/org.apache.maven/maven-compat@3.5.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-core-3.5.4.jar": "pkg:maven/org.apache.maven/maven-core@3.5.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-embedder-3.5.4.jar": "pkg:maven/org.apache.maven/maven-embedder@3.5.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-interceptor-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven-interceptor@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-model-3.5.4.jar": "pkg:maven/org.apache.maven/maven-model@3.5.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-model-builder-3.5.4.jar": "pkg:maven/org.apache.maven/maven-model-builder@3.5.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-plugin-api-3.5.4.jar": "pkg:maven/org.apache.maven/maven-plugin-api@3.5.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-plugin.jar": "pkg:maven/org.jenkins-ci.main/maven-plugin@3.10.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-plugin.jar:classworlds.jar": "pkg:maven/org.codehaus.classworlds/classworlds@1.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-reporting-api-3.0.jar": "pkg:maven/org.apache.maven.reporting/maven-reporting-api@3.0",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-repository-metadata-3.5.4.jar": "pkg:maven/org.apache.maven/maven-repository-metadata@3.5.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-api-1.1.1.jar": "pkg:maven/org.apache.maven.resolver/maven-resolver-api@1.1.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-connector-basic-1.1.1.jar": "pkg:maven/org.apache.maven.resolver/maven-resolver-connector-basic@1.1.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-impl-1.1.1.jar": "pkg:maven/org.apache.maven.resolver/maven-resolver-impl@1.1.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-provider-3.5.4.jar": "pkg:maven/org.apache.maven/maven-resolver-provider@3.5.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-spi-1.1.1.jar": "pkg:maven/org.apache.maven.resolver/maven-resolver-spi@1.1.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-transport-wagon-1.1.1.jar": "pkg:maven/org.apache.maven.resolver/maven-resolver-transport-wagon@1.1.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-resolver-util-1.1.1.jar": "pkg:maven/org.apache.maven.resolver/maven-resolver-util@1.1.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-settings-3.5.4.jar": "pkg:maven/org.apache.maven/maven-settings@3.5.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-settings-builder-3.5.4.jar": "pkg:maven/org.apache.maven/maven-settings-builder@3.5.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven-shared-utils-3.2.1.jar": "pkg:maven/org.apache.maven.shared/maven-shared-utils@3.2.1",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven2.1-interceptor-1.2.jar": "pkg:maven/org.jvnet.hudson/maven2.1-interceptor@1.2",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven3-agent-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven3-agent@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven3-interceptor-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven3-interceptor@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven3-interceptor-commons-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven3-interceptor-commons@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven31-agent-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven31-agent@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven31-interceptor-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven31-interceptor@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven32-agent-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven32-agent@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven32-interceptor-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven32-interceptor@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven33-agent-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven33-agent@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven33-interceptor-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven33-interceptor@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven35-agent-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven35-agent@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/maven35-interceptor-1.13.jar": "pkg:maven/org.jenkins-ci.main.maven/maven35-interceptor@1.13",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/org.eclipse.sisu.inject-0.3.3.jar": "pkg:maven/org.eclipse.sisu.inject/org.eclipse.sisu.inject@0.3.3",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/org.eclipse.sisu.plexus-0.3.3.jar": "pkg:maven/org.eclipse.sisu.plexus/org.eclipse.sisu.plexus@0.3.3",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/plexus-cipher-1.8.jar": "pkg:maven/org.codehaus.plexus/plexus-cipher@1.8",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/plexus-classworlds-2.6.0.jar": "pkg:maven/org.codehaus.plexus/plexus-classworlds@2.6.0",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/plexus-component-annotations-2.1.0.jar": "pkg:maven/org.codehaus.plexus/plexus-component-annotations@2.1.0",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/plexus-interactivity-api-1.0.jar": "pkg:maven/org.codehaus.plexus/plexus-interactivity-api@1.0",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/plexus-interpolation-1.24.jar": "pkg:maven/org.codehaus.plexus/plexus-interpolation@1.24",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/plexus-sec-dispatcher-1.4.jar": "pkg:maven/org.sonatype.plexus/plexus-sec-dispatcher@1.4",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/plexus-utils-3.3.0.jar": "pkg:maven/org.codehaus.plexus/plexus-utils@3.3.0",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/slf4j-api-1.7.30.jar": "pkg:maven/org.slf4j/slf4j-api@1.7.30",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/wagon-file-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-file@3.4.3",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/wagon-ftp-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-ftp@3.4.3",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/wagon-http-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-http@3.4.3",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/wagon-http-shared-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-http-shared@3.4.3",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/wagon-provider-api-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-provider-api@3.4.3",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/wagon-ssh-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-ssh@3.4.3",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/wagon-ssh-common-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-ssh-common@3.4.3",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/wagon-ssh-external-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-ssh-external@3.4.3",
|
||||||
|
"/packages/maven-plugin.hpi:WEB-INF/lib/wagon-webdav-jackrabbit-3.4.3.jar": "pkg:maven/org.apache.maven.wagon/wagon-webdav-jackrabbit@3.4.3",
|
||||||
"/packages/maven-shared-utils-3.2.1.jar": "pkg:maven/org.apache.maven.shared/maven-shared-utils@3.2.1",
|
"/packages/maven-shared-utils-3.2.1.jar": "pkg:maven/org.apache.maven.shared/maven-shared-utils@3.2.1",
|
||||||
"/packages/mesos-1.7.1.jar": "pkg:maven/org.apache.mesos/mesos@1.7.1",
|
"/packages/mesos-1.7.1.jar": "pkg:maven/org.apache.mesos/mesos@1.7.1",
|
||||||
"/packages/minio-8.3.8.jar": "pkg:maven/io.minio/minio@8.3.8",
|
"/packages/minio-8.3.8.jar": "pkg:maven/io.minio/minio@8.3.8",
|
||||||
"/packages/ms-mcms-5.3.1.jar": "pkg:maven/net.mingsoft/ms-mcms@5.3.1",
|
"/packages/ms-mcms-5.3.1.jar": "pkg:maven/net.mingsoft/ms-mcms@5.3.1",
|
||||||
"/packages/my-app-1.jar:com.fasterxml:classmate": "pkg:maven/com.fasterxml/classmate@1.5.1",
|
"/packages/my-app-1.jar": "pkg:maven/com.mycompany.app/my-app@1",
|
||||||
"/packages/my-app-1.jar:com.fasterxml.jackson.core:jackson-annotations": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.13.2",
|
"/packages/my-app-1.jar:com.fasterxml.jackson.core:jackson-annotations": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.13.2",
|
||||||
"/packages/my-app-1.jar:com.fasterxml.jackson.core:jackson-core": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.13.2",
|
"/packages/my-app-1.jar:com.fasterxml.jackson.core:jackson-core": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.13.2",
|
||||||
"/packages/my-app-1.jar:com.fasterxml.jackson.core:jackson-databind": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.0",
|
"/packages/my-app-1.jar:com.fasterxml.jackson.core:jackson-databind": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.0",
|
||||||
|
"/packages/my-app-1.jar:com.fasterxml:classmate": "pkg:maven/com.fasterxml/classmate@1.5.1",
|
||||||
"/packages/my-app-1.jar:com.google.errorprone:error_prone_annotations": "pkg:maven/com.google.errorprone/error_prone_annotations@2.0.18",
|
"/packages/my-app-1.jar:com.google.errorprone:error_prone_annotations": "pkg:maven/com.google.errorprone/error_prone_annotations@2.0.18",
|
||||||
"/packages/my-app-1.jar:com.google.guava:guava": "pkg:maven/com.google.guava/guava@23.0",
|
"/packages/my-app-1.jar:com.google.guava:guava": "pkg:maven/com.google.guava/guava@23.0",
|
||||||
"/packages/my-app-1.jar:com.google.j2objc:j2objc-annotations": "pkg:maven/com.google.j2objc/j2objc-annotations@1.1",
|
"/packages/my-app-1.jar:com.google.j2objc:j2objc-annotations": "pkg:maven/com.google.j2objc/j2objc-annotations@1.1",
|
||||||
@@ -395,23 +702,23 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/my-app-1.jar:commons-logging:commons-logging": "pkg:maven/commons-logging/commons-logging@1.2",
|
"/packages/my-app-1.jar:commons-logging:commons-logging": "pkg:maven/commons-logging/commons-logging@1.2",
|
||||||
"/packages/my-app-1.jar:commons-validator:commons-validator": "pkg:maven/commons-validator/commons-validator@1.5.1",
|
"/packages/my-app-1.jar:commons-validator:commons-validator": "pkg:maven/commons-validator/commons-validator@1.5.1",
|
||||||
"/packages/my-app-1.jar:io.netty:netty-buffer": "pkg:maven/io.netty/netty-buffer@4.1.52.Final",
|
"/packages/my-app-1.jar:io.netty:netty-buffer": "pkg:maven/io.netty/netty-buffer@4.1.52.Final",
|
||||||
|
"/packages/my-app-1.jar:io.netty:netty-codec": "pkg:maven/io.netty/netty-codec@4.1.52.Final",
|
||||||
"/packages/my-app-1.jar:io.netty:netty-codec-dns": "pkg:maven/io.netty/netty-codec-dns@4.1.63.Final",
|
"/packages/my-app-1.jar:io.netty:netty-codec-dns": "pkg:maven/io.netty/netty-codec-dns@4.1.63.Final",
|
||||||
"/packages/my-app-1.jar:io.netty:netty-codec-http": "pkg:maven/io.netty/netty-codec-http@4.1.63.Final",
|
"/packages/my-app-1.jar:io.netty:netty-codec-http": "pkg:maven/io.netty/netty-codec-http@4.1.63.Final",
|
||||||
"/packages/my-app-1.jar:io.netty:netty-codec-socks": "pkg:maven/io.netty/netty-codec-socks@4.1.63.Final",
|
"/packages/my-app-1.jar:io.netty:netty-codec-socks": "pkg:maven/io.netty/netty-codec-socks@4.1.63.Final",
|
||||||
"/packages/my-app-1.jar:io.netty:netty-codec": "pkg:maven/io.netty/netty-codec@4.1.52.Final",
|
|
||||||
"/packages/my-app-1.jar:io.netty:netty-common": "pkg:maven/io.netty/netty-common@4.1.52.Final",
|
"/packages/my-app-1.jar:io.netty:netty-common": "pkg:maven/io.netty/netty-common@4.1.52.Final",
|
||||||
"/packages/my-app-1.jar:io.netty:netty-handler-proxy": "pkg:maven/io.netty/netty-handler-proxy@4.1.63.Final",
|
|
||||||
"/packages/my-app-1.jar:io.netty:netty-handler": "pkg:maven/io.netty/netty-handler@4.1.52.Final",
|
"/packages/my-app-1.jar:io.netty:netty-handler": "pkg:maven/io.netty/netty-handler@4.1.52.Final",
|
||||||
"/packages/my-app-1.jar:io.netty:netty-resolver-dns-native-macos": "pkg:maven/io.netty/netty-resolver-dns-native-macos@4.1.63.Final",
|
"/packages/my-app-1.jar:io.netty:netty-handler-proxy": "pkg:maven/io.netty/netty-handler-proxy@4.1.63.Final",
|
||||||
"/packages/my-app-1.jar:io.netty:netty-resolver-dns": "pkg:maven/io.netty/netty-resolver-dns@4.1.63.Final",
|
|
||||||
"/packages/my-app-1.jar:io.netty:netty-resolver": "pkg:maven/io.netty/netty-resolver@4.1.52.Final",
|
"/packages/my-app-1.jar:io.netty:netty-resolver": "pkg:maven/io.netty/netty-resolver@4.1.52.Final",
|
||||||
|
"/packages/my-app-1.jar:io.netty:netty-resolver-dns": "pkg:maven/io.netty/netty-resolver-dns@4.1.63.Final",
|
||||||
|
"/packages/my-app-1.jar:io.netty:netty-resolver-dns-native-macos": "pkg:maven/io.netty/netty-resolver-dns-native-macos@4.1.63.Final",
|
||||||
|
"/packages/my-app-1.jar:io.netty:netty-transport": "pkg:maven/io.netty/netty-transport@4.1.52.Final",
|
||||||
"/packages/my-app-1.jar:io.netty:netty-transport-native-epoll": "pkg:maven/io.netty/netty-transport-native-epoll@4.1.63.Final",
|
"/packages/my-app-1.jar:io.netty:netty-transport-native-epoll": "pkg:maven/io.netty/netty-transport-native-epoll@4.1.63.Final",
|
||||||
"/packages/my-app-1.jar:io.netty:netty-transport-native-unix-common": "pkg:maven/io.netty/netty-transport-native-unix-common@4.1.63.Final",
|
"/packages/my-app-1.jar:io.netty:netty-transport-native-unix-common": "pkg:maven/io.netty/netty-transport-native-unix-common@4.1.63.Final",
|
||||||
"/packages/my-app-1.jar:io.netty:netty-transport": "pkg:maven/io.netty/netty-transport@4.1.52.Final",
|
|
||||||
"/packages/my-app-1.jar:io.prometheus:simpleclient_common": "pkg:maven/io.prometheus/simpleclient_common@0.9.0",
|
|
||||||
"/packages/my-app-1.jar:io.prometheus:simpleclient": "pkg:maven/io.prometheus/simpleclient@0.9.0",
|
"/packages/my-app-1.jar:io.prometheus:simpleclient": "pkg:maven/io.prometheus/simpleclient@0.9.0",
|
||||||
"/packages/my-app-1.jar:io.vavr:vavr-match": "pkg:maven/io.vavr/vavr-match@0.10.2",
|
"/packages/my-app-1.jar:io.prometheus:simpleclient_common": "pkg:maven/io.prometheus/simpleclient_common@0.9.0",
|
||||||
"/packages/my-app-1.jar:io.vavr:vavr": "pkg:maven/io.vavr/vavr@0.10.2",
|
"/packages/my-app-1.jar:io.vavr:vavr": "pkg:maven/io.vavr/vavr@0.10.2",
|
||||||
|
"/packages/my-app-1.jar:io.vavr:vavr-match": "pkg:maven/io.vavr/vavr-match@0.10.2",
|
||||||
"/packages/my-app-1.jar:jakarta.validation:jakarta.validation-api": "pkg:maven/jakarta.validation/jakarta.validation-api@2.0.2",
|
"/packages/my-app-1.jar:jakarta.validation:jakarta.validation-api": "pkg:maven/jakarta.validation/jakarta.validation-api@2.0.2",
|
||||||
"/packages/my-app-1.jar:javax.servlet:javax.servlet-api": "pkg:maven/javax.servlet/javax.servlet-api@3.1.0",
|
"/packages/my-app-1.jar:javax.servlet:javax.servlet-api": "pkg:maven/javax.servlet/javax.servlet-api@3.1.0",
|
||||||
"/packages/my-app-1.jar:org.apache.activemq.protobuf:activemq-protobuf": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1",
|
"/packages/my-app-1.jar:org.apache.activemq.protobuf:activemq-protobuf": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1",
|
||||||
@@ -419,14 +726,14 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/my-app-1.jar:org.apache.commons:commons-lang3": "pkg:maven/org.apache.commons/commons-lang3@3.10",
|
"/packages/my-app-1.jar:org.apache.commons:commons-lang3": "pkg:maven/org.apache.commons/commons-lang3@3.10",
|
||||||
"/packages/my-app-1.jar:org.apache.maven.shared:maven-shared-utils": "pkg:maven/org.apache.maven.shared/maven-shared-utils@3.3.4",
|
"/packages/my-app-1.jar:org.apache.maven.shared:maven-shared-utils": "pkg:maven/org.apache.maven.shared/maven-shared-utils@3.3.4",
|
||||||
"/packages/my-app-1.jar:org.codehaus.mojo:animal-sniffer-annotations": "pkg:maven/org.codehaus.mojo/animal-sniffer-annotations@1.14",
|
"/packages/my-app-1.jar:org.codehaus.mojo:animal-sniffer-annotations": "pkg:maven/org.codehaus.mojo/animal-sniffer-annotations@1.14",
|
||||||
|
"/packages/my-app-1.jar:org.eclipse.jetty.http2:http2-common": "pkg:maven/org.eclipse.jetty.http2/http2-common@9.4.43.v20210629",
|
||||||
|
"/packages/my-app-1.jar:org.eclipse.jetty.http2:http2-hpack": "pkg:maven/org.eclipse.jetty.http2/http2-hpack@9.4.43.v20210629",
|
||||||
|
"/packages/my-app-1.jar:org.eclipse.jetty.toolchain.setuid:jetty-setuid-java": "pkg:maven/org.eclipse.jetty.toolchain.setuid/jetty-setuid-java@1.0.4",
|
||||||
"/packages/my-app-1.jar:org.eclipse.jetty:jetty-client": "pkg:maven/org.eclipse.jetty/jetty-client@9.4.43.v20210629",
|
"/packages/my-app-1.jar:org.eclipse.jetty:jetty-client": "pkg:maven/org.eclipse.jetty/jetty-client@9.4.43.v20210629",
|
||||||
"/packages/my-app-1.jar:org.eclipse.jetty:jetty-http": "pkg:maven/org.eclipse.jetty/jetty-http@9.4.43.v20210629",
|
"/packages/my-app-1.jar:org.eclipse.jetty:jetty-http": "pkg:maven/org.eclipse.jetty/jetty-http@9.4.43.v20210629",
|
||||||
"/packages/my-app-1.jar:org.eclipse.jetty:jetty-io": "pkg:maven/org.eclipse.jetty/jetty-io@9.4.43.v20210629",
|
"/packages/my-app-1.jar:org.eclipse.jetty:jetty-io": "pkg:maven/org.eclipse.jetty/jetty-io@9.4.43.v20210629",
|
||||||
"/packages/my-app-1.jar:org.eclipse.jetty:jetty-server": "pkg:maven/org.eclipse.jetty/jetty-server@9.1.0.M0",
|
"/packages/my-app-1.jar:org.eclipse.jetty:jetty-server": "pkg:maven/org.eclipse.jetty/jetty-server@9.1.0.M0",
|
||||||
"/packages/my-app-1.jar:org.eclipse.jetty:jetty-util": "pkg:maven/org.eclipse.jetty/jetty-util@9.4.43.v20210629",
|
"/packages/my-app-1.jar:org.eclipse.jetty:jetty-util": "pkg:maven/org.eclipse.jetty/jetty-util@9.4.43.v20210629",
|
||||||
"/packages/my-app-1.jar:org.eclipse.jetty.http2:http2-common": "pkg:maven/org.eclipse.jetty.http2/http2-common@9.4.43.v20210629",
|
|
||||||
"/packages/my-app-1.jar:org.eclipse.jetty.http2:http2-hpack": "pkg:maven/org.eclipse.jetty.http2/http2-hpack@9.4.43.v20210629",
|
|
||||||
"/packages/my-app-1.jar:org.eclipse.jetty.toolchain.setuid:jetty-setuid-java": "pkg:maven/org.eclipse.jetty.toolchain.setuid/jetty-setuid-java@1.0.4",
|
|
||||||
"/packages/my-app-1.jar:org.everit.json:org.everit.json.schema": "pkg:maven/org.everit.json/org.everit.json.schema@1.5.1",
|
"/packages/my-app-1.jar:org.everit.json:org.everit.json.schema": "pkg:maven/org.everit.json/org.everit.json.schema@1.5.1",
|
||||||
"/packages/my-app-1.jar:org.hibernate.validator:hibernate-validator": "pkg:maven/org.hibernate.validator/hibernate-validator@6.2.4.Final",
|
"/packages/my-app-1.jar:org.hibernate.validator:hibernate-validator": "pkg:maven/org.hibernate.validator/hibernate-validator@6.2.4.Final",
|
||||||
"/packages/my-app-1.jar:org.jboss.logging:jboss-logging": "pkg:maven/org.jboss.logging/jboss-logging@3.4.1.Final",
|
"/packages/my-app-1.jar:org.jboss.logging:jboss-logging": "pkg:maven/org.jboss.logging/jboss-logging@3.4.1.Final",
|
||||||
@@ -442,9 +749,9 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/my-app-1.jar:org.sonarsource.python:python-checks": "pkg:maven/org.sonarsource.python/python-checks@3.4.1.8066",
|
"/packages/my-app-1.jar:org.sonarsource.python:python-checks": "pkg:maven/org.sonarsource.python/python-checks@3.4.1.8066",
|
||||||
"/packages/my-app-1.jar:org.sonarsource.python:python-frontend": "pkg:maven/org.sonarsource.python/python-frontend@3.4.1.8066",
|
"/packages/my-app-1.jar:org.sonarsource.python:python-frontend": "pkg:maven/org.sonarsource.python/python-frontend@3.4.1.8066",
|
||||||
"/packages/my-app-1.jar:org.sonarsource.sslr:sslr-core": "pkg:maven/org.sonarsource.sslr/sslr-core@1.24.0.633",
|
"/packages/my-app-1.jar:org.sonarsource.sslr:sslr-core": "pkg:maven/org.sonarsource.sslr/sslr-core@1.24.0.633",
|
||||||
"/packages/my-app-1.jar": "pkg:maven/com.mycompany.app/my-app@1",
|
|
||||||
"/packages/netty-reactive-streams-2.0.6.jar": "pkg:maven/com.typesafe.netty/netty-reactive-streams@2.0.6",
|
"/packages/netty-reactive-streams-2.0.6.jar": "pkg:maven/com.typesafe.netty/netty-reactive-streams@2.0.6",
|
||||||
"/packages/nifi-utils-1.12.0.jar": "pkg:maven/org.apache.nifi/nifi-utils@1.12.0",
|
"/packages/nifi-utils-1.12.0.jar": "pkg:maven/org.apache.nifi/nifi-utils@1.12.0",
|
||||||
|
"/packages/nomad.hpi": "pkg:maven/org.jenkins-ci.plugins/nomad@0.7.4",
|
||||||
"/packages/nomad.hpi:WEB-INF/lib/annotations-13.0.jar": "pkg:maven/org.jetbrains/annotations@13.0",
|
"/packages/nomad.hpi:WEB-INF/lib/annotations-13.0.jar": "pkg:maven/org.jetbrains/annotations@13.0",
|
||||||
"/packages/nomad.hpi:WEB-INF/lib/gson-2.8.6.jar": "pkg:maven/com.google.code.gson/gson@2.8.6",
|
"/packages/nomad.hpi:WEB-INF/lib/gson-2.8.6.jar": "pkg:maven/com.google.code.gson/gson@2.8.6",
|
||||||
"/packages/nomad.hpi:WEB-INF/lib/json-20200518.jar": "pkg:maven/org.json/json@20200518",
|
"/packages/nomad.hpi:WEB-INF/lib/json-20200518.jar": "pkg:maven/org.json/json@20200518",
|
||||||
@@ -453,15 +760,19 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/nomad.hpi:WEB-INF/lib/nomad.jar": "pkg:maven/org.jenkins-ci.plugins/nomad@0.7.4",
|
"/packages/nomad.hpi:WEB-INF/lib/nomad.jar": "pkg:maven/org.jenkins-ci.plugins/nomad@0.7.4",
|
||||||
"/packages/nomad.hpi:WEB-INF/lib/okhttp-4.5.0.jar": "pkg:maven/com.squareup.okhttp3/okhttp@4.5.0",
|
"/packages/nomad.hpi:WEB-INF/lib/okhttp-4.5.0.jar": "pkg:maven/com.squareup.okhttp3/okhttp@4.5.0",
|
||||||
"/packages/nomad.hpi:WEB-INF/lib/okio-2.5.0.jar": "pkg:maven/com.squareup.okio/okio@2.5.0",
|
"/packages/nomad.hpi:WEB-INF/lib/okio-2.5.0.jar": "pkg:maven/com.squareup.okio/okio@2.5.0",
|
||||||
"/packages/nomad.hpi": "pkg:maven/org.jenkins-ci.plugins/nomad@0.7.4",
|
"/packages/nuget.hpi": "pkg:maven/org.jenkins-ci.plugins/nuget@1.0",
|
||||||
|
"/packages/nuget.hpi:WEB-INF/lib/envinject-lib-1.19.jar": "pkg:maven/org.jenkins-ci.lib/envinject-lib@1.19",
|
||||||
|
"/packages/nuget.hpi:WEB-INF/lib/nuget.jar": "pkg:maven/org.jenkins-ci.plugins/nuget@1.0",
|
||||||
|
"/packages/nuget.hpi:WEB-INF/lib/xtrigger-lib-0.33.jar": "pkg:maven/org.jenkins-ci.lib/xtrigger-lib@0.33",
|
||||||
"/packages/openmeetings-util-4.0.9.jar": "pkg:maven/org.apache.openmeetings/openmeetings-util@4.0.9",
|
"/packages/openmeetings-util-4.0.9.jar": "pkg:maven/org.apache.openmeetings/openmeetings-util@4.0.9",
|
||||||
"/packages/org.eclipse.ant.core-3.7.0.jar": "pkg:maven/org.eclipse.platform/org.eclipse.ant.core@3.7.0",
|
"/packages/org.eclipse.ant.core-3.7.0.jar": "pkg:maven/org.eclipse.platform/org.eclipse.ant.core@3.7.0",
|
||||||
"/packages/org.eclipse.osgi-3.18.0.jar": "pkg:maven/org.eclipse.platform/org.eclipse.osgi@3.18.0",
|
"/packages/org.eclipse.osgi-3.18.0.jar": "pkg:maven/org.eclipse.platform/org.eclipse.osgi@3.18.0",
|
||||||
"/packages/org.everit.json.schema-1.5.1.jar": "pkg:maven/org.everit.json/org.everit.json.schema@1.5.1",
|
"/packages/org.everit.json.schema-1.5.1.jar": "pkg:maven/org.everit.json/org.everit.json.schema@1.5.1",
|
||||||
"/packages/original-my-app-1.jar:com.fasterxml:classmate": "pkg:maven/com.fasterxml/classmate@1.5.1",
|
"/packages/original-my-app-1.jar": "pkg:maven/com.mycompany.app/my-app@1",
|
||||||
"/packages/original-my-app-1.jar:com.fasterxml.jackson.core:jackson-annotations": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.13.2",
|
"/packages/original-my-app-1.jar:com.fasterxml.jackson.core:jackson-annotations": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.13.2",
|
||||||
"/packages/original-my-app-1.jar:com.fasterxml.jackson.core:jackson-core": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.13.2",
|
"/packages/original-my-app-1.jar:com.fasterxml.jackson.core:jackson-core": "pkg:maven/com.fasterxml.jackson.core/jackson-core@2.13.2",
|
||||||
"/packages/original-my-app-1.jar:com.fasterxml.jackson.core:jackson-databind": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.0",
|
"/packages/original-my-app-1.jar:com.fasterxml.jackson.core:jackson-databind": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.0",
|
||||||
|
"/packages/original-my-app-1.jar:com.fasterxml:classmate": "pkg:maven/com.fasterxml/classmate@1.5.1",
|
||||||
"/packages/original-my-app-1.jar:com.google.errorprone:error_prone_annotations": "pkg:maven/com.google.errorprone/error_prone_annotations@2.0.18",
|
"/packages/original-my-app-1.jar:com.google.errorprone:error_prone_annotations": "pkg:maven/com.google.errorprone/error_prone_annotations@2.0.18",
|
||||||
"/packages/original-my-app-1.jar:com.google.guava:guava": "pkg:maven/com.google.guava/guava@23.0",
|
"/packages/original-my-app-1.jar:com.google.guava:guava": "pkg:maven/com.google.guava/guava@23.0",
|
||||||
"/packages/original-my-app-1.jar:com.google.j2objc:j2objc-annotations": "pkg:maven/com.google.j2objc/j2objc-annotations@1.1",
|
"/packages/original-my-app-1.jar:com.google.j2objc:j2objc-annotations": "pkg:maven/com.google.j2objc/j2objc-annotations@1.1",
|
||||||
@@ -475,23 +786,23 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/original-my-app-1.jar:commons-logging:commons-logging": "pkg:maven/commons-logging/commons-logging@1.2",
|
"/packages/original-my-app-1.jar:commons-logging:commons-logging": "pkg:maven/commons-logging/commons-logging@1.2",
|
||||||
"/packages/original-my-app-1.jar:commons-validator:commons-validator": "pkg:maven/commons-validator/commons-validator@1.5.1",
|
"/packages/original-my-app-1.jar:commons-validator:commons-validator": "pkg:maven/commons-validator/commons-validator@1.5.1",
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-buffer": "pkg:maven/io.netty/netty-buffer@4.1.52.Final",
|
"/packages/original-my-app-1.jar:io.netty:netty-buffer": "pkg:maven/io.netty/netty-buffer@4.1.52.Final",
|
||||||
|
"/packages/original-my-app-1.jar:io.netty:netty-codec": "pkg:maven/io.netty/netty-codec@4.1.52.Final",
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-codec-dns": "pkg:maven/io.netty/netty-codec-dns@4.1.63.Final",
|
"/packages/original-my-app-1.jar:io.netty:netty-codec-dns": "pkg:maven/io.netty/netty-codec-dns@4.1.63.Final",
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-codec-http": "pkg:maven/io.netty/netty-codec-http@4.1.63.Final",
|
"/packages/original-my-app-1.jar:io.netty:netty-codec-http": "pkg:maven/io.netty/netty-codec-http@4.1.63.Final",
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-codec-socks": "pkg:maven/io.netty/netty-codec-socks@4.1.63.Final",
|
"/packages/original-my-app-1.jar:io.netty:netty-codec-socks": "pkg:maven/io.netty/netty-codec-socks@4.1.63.Final",
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-codec": "pkg:maven/io.netty/netty-codec@4.1.52.Final",
|
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-common": "pkg:maven/io.netty/netty-common@4.1.52.Final",
|
"/packages/original-my-app-1.jar:io.netty:netty-common": "pkg:maven/io.netty/netty-common@4.1.52.Final",
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-handler-proxy": "pkg:maven/io.netty/netty-handler-proxy@4.1.63.Final",
|
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-handler": "pkg:maven/io.netty/netty-handler@4.1.52.Final",
|
"/packages/original-my-app-1.jar:io.netty:netty-handler": "pkg:maven/io.netty/netty-handler@4.1.52.Final",
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-resolver-dns-native-macos": "pkg:maven/io.netty/netty-resolver-dns-native-macos@4.1.63.Final",
|
"/packages/original-my-app-1.jar:io.netty:netty-handler-proxy": "pkg:maven/io.netty/netty-handler-proxy@4.1.63.Final",
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-resolver-dns": "pkg:maven/io.netty/netty-resolver-dns@4.1.63.Final",
|
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-resolver": "pkg:maven/io.netty/netty-resolver@4.1.52.Final",
|
"/packages/original-my-app-1.jar:io.netty:netty-resolver": "pkg:maven/io.netty/netty-resolver@4.1.52.Final",
|
||||||
|
"/packages/original-my-app-1.jar:io.netty:netty-resolver-dns": "pkg:maven/io.netty/netty-resolver-dns@4.1.63.Final",
|
||||||
|
"/packages/original-my-app-1.jar:io.netty:netty-resolver-dns-native-macos": "pkg:maven/io.netty/netty-resolver-dns-native-macos@4.1.63.Final",
|
||||||
|
"/packages/original-my-app-1.jar:io.netty:netty-transport": "pkg:maven/io.netty/netty-transport@4.1.52.Final",
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-transport-native-epoll": "pkg:maven/io.netty/netty-transport-native-epoll@4.1.63.Final",
|
"/packages/original-my-app-1.jar:io.netty:netty-transport-native-epoll": "pkg:maven/io.netty/netty-transport-native-epoll@4.1.63.Final",
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-transport-native-unix-common": "pkg:maven/io.netty/netty-transport-native-unix-common@4.1.63.Final",
|
"/packages/original-my-app-1.jar:io.netty:netty-transport-native-unix-common": "pkg:maven/io.netty/netty-transport-native-unix-common@4.1.63.Final",
|
||||||
"/packages/original-my-app-1.jar:io.netty:netty-transport": "pkg:maven/io.netty/netty-transport@4.1.52.Final",
|
|
||||||
"/packages/original-my-app-1.jar:io.prometheus:simpleclient_common": "pkg:maven/io.prometheus/simpleclient_common@0.9.0",
|
|
||||||
"/packages/original-my-app-1.jar:io.prometheus:simpleclient": "pkg:maven/io.prometheus/simpleclient@0.9.0",
|
"/packages/original-my-app-1.jar:io.prometheus:simpleclient": "pkg:maven/io.prometheus/simpleclient@0.9.0",
|
||||||
"/packages/original-my-app-1.jar:io.vavr:vavr-match": "pkg:maven/io.vavr/vavr-match@0.10.2",
|
"/packages/original-my-app-1.jar:io.prometheus:simpleclient_common": "pkg:maven/io.prometheus/simpleclient_common@0.9.0",
|
||||||
"/packages/original-my-app-1.jar:io.vavr:vavr": "pkg:maven/io.vavr/vavr@0.10.2",
|
"/packages/original-my-app-1.jar:io.vavr:vavr": "pkg:maven/io.vavr/vavr@0.10.2",
|
||||||
|
"/packages/original-my-app-1.jar:io.vavr:vavr-match": "pkg:maven/io.vavr/vavr-match@0.10.2",
|
||||||
"/packages/original-my-app-1.jar:jakarta.validation:jakarta.validation-api": "pkg:maven/jakarta.validation/jakarta.validation-api@2.0.2",
|
"/packages/original-my-app-1.jar:jakarta.validation:jakarta.validation-api": "pkg:maven/jakarta.validation/jakarta.validation-api@2.0.2",
|
||||||
"/packages/original-my-app-1.jar:javax.servlet:javax.servlet-api": "pkg:maven/javax.servlet/javax.servlet-api@3.1.0",
|
"/packages/original-my-app-1.jar:javax.servlet:javax.servlet-api": "pkg:maven/javax.servlet/javax.servlet-api@3.1.0",
|
||||||
"/packages/original-my-app-1.jar:org.apache.activemq.protobuf:activemq-protobuf": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1",
|
"/packages/original-my-app-1.jar:org.apache.activemq.protobuf:activemq-protobuf": "pkg:maven/org.apache.activemq.protobuf/activemq-protobuf@1.1",
|
||||||
@@ -499,14 +810,14 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/original-my-app-1.jar:org.apache.commons:commons-lang3": "pkg:maven/org.apache.commons/commons-lang3@3.10",
|
"/packages/original-my-app-1.jar:org.apache.commons:commons-lang3": "pkg:maven/org.apache.commons/commons-lang3@3.10",
|
||||||
"/packages/original-my-app-1.jar:org.apache.maven.shared:maven-shared-utils": "pkg:maven/org.apache.maven.shared/maven-shared-utils@3.3.4",
|
"/packages/original-my-app-1.jar:org.apache.maven.shared:maven-shared-utils": "pkg:maven/org.apache.maven.shared/maven-shared-utils@3.3.4",
|
||||||
"/packages/original-my-app-1.jar:org.codehaus.mojo:animal-sniffer-annotations": "pkg:maven/org.codehaus.mojo/animal-sniffer-annotations@1.14",
|
"/packages/original-my-app-1.jar:org.codehaus.mojo:animal-sniffer-annotations": "pkg:maven/org.codehaus.mojo/animal-sniffer-annotations@1.14",
|
||||||
|
"/packages/original-my-app-1.jar:org.eclipse.jetty.http2:http2-common": "pkg:maven/org.eclipse.jetty.http2/http2-common@9.4.43.v20210629",
|
||||||
|
"/packages/original-my-app-1.jar:org.eclipse.jetty.http2:http2-hpack": "pkg:maven/org.eclipse.jetty.http2/http2-hpack@9.4.43.v20210629",
|
||||||
|
"/packages/original-my-app-1.jar:org.eclipse.jetty.toolchain.setuid:jetty-setuid-java": "pkg:maven/org.eclipse.jetty.toolchain.setuid/jetty-setuid-java@1.0.4",
|
||||||
"/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-client": "pkg:maven/org.eclipse.jetty/jetty-client@9.4.43.v20210629",
|
"/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-client": "pkg:maven/org.eclipse.jetty/jetty-client@9.4.43.v20210629",
|
||||||
"/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-http": "pkg:maven/org.eclipse.jetty/jetty-http@9.4.43.v20210629",
|
"/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-http": "pkg:maven/org.eclipse.jetty/jetty-http@9.4.43.v20210629",
|
||||||
"/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-io": "pkg:maven/org.eclipse.jetty/jetty-io@9.4.43.v20210629",
|
"/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-io": "pkg:maven/org.eclipse.jetty/jetty-io@9.4.43.v20210629",
|
||||||
"/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-server": "pkg:maven/org.eclipse.jetty/jetty-server@9.1.0.M0",
|
"/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-server": "pkg:maven/org.eclipse.jetty/jetty-server@9.1.0.M0",
|
||||||
"/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-util": "pkg:maven/org.eclipse.jetty/jetty-util@9.4.43.v20210629",
|
"/packages/original-my-app-1.jar:org.eclipse.jetty:jetty-util": "pkg:maven/org.eclipse.jetty/jetty-util@9.4.43.v20210629",
|
||||||
"/packages/original-my-app-1.jar:org.eclipse.jetty.http2:http2-common": "pkg:maven/org.eclipse.jetty.http2/http2-common@9.4.43.v20210629",
|
|
||||||
"/packages/original-my-app-1.jar:org.eclipse.jetty.http2:http2-hpack": "pkg:maven/org.eclipse.jetty.http2/http2-hpack@9.4.43.v20210629",
|
|
||||||
"/packages/original-my-app-1.jar:org.eclipse.jetty.toolchain.setuid:jetty-setuid-java": "pkg:maven/org.eclipse.jetty.toolchain.setuid/jetty-setuid-java@1.0.4",
|
|
||||||
"/packages/original-my-app-1.jar:org.everit.json:org.everit.json.schema": "pkg:maven/org.everit.json/org.everit.json.schema@1.5.1",
|
"/packages/original-my-app-1.jar:org.everit.json:org.everit.json.schema": "pkg:maven/org.everit.json/org.everit.json.schema@1.5.1",
|
||||||
"/packages/original-my-app-1.jar:org.hibernate.validator:hibernate-validator": "pkg:maven/org.hibernate.validator/hibernate-validator@6.2.4.Final",
|
"/packages/original-my-app-1.jar:org.hibernate.validator:hibernate-validator": "pkg:maven/org.hibernate.validator/hibernate-validator@6.2.4.Final",
|
||||||
"/packages/original-my-app-1.jar:org.jboss.logging:jboss-logging": "pkg:maven/org.jboss.logging/jboss-logging@3.4.1.Final",
|
"/packages/original-my-app-1.jar:org.jboss.logging:jboss-logging": "pkg:maven/org.jboss.logging/jboss-logging@3.4.1.Final",
|
||||||
@@ -522,7 +833,6 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/original-my-app-1.jar:org.sonarsource.python:python-checks": "pkg:maven/org.sonarsource.python/python-checks@3.4.1.8066",
|
"/packages/original-my-app-1.jar:org.sonarsource.python:python-checks": "pkg:maven/org.sonarsource.python/python-checks@3.4.1.8066",
|
||||||
"/packages/original-my-app-1.jar:org.sonarsource.python:python-frontend": "pkg:maven/org.sonarsource.python/python-frontend@3.4.1.8066",
|
"/packages/original-my-app-1.jar:org.sonarsource.python:python-frontend": "pkg:maven/org.sonarsource.python/python-frontend@3.4.1.8066",
|
||||||
"/packages/original-my-app-1.jar:org.sonarsource.sslr:sslr-core": "pkg:maven/org.sonarsource.sslr/sslr-core@1.24.0.633",
|
"/packages/original-my-app-1.jar:org.sonarsource.sslr:sslr-core": "pkg:maven/org.sonarsource.sslr/sslr-core@1.24.0.633",
|
||||||
"/packages/original-my-app-1.jar": "pkg:maven/com.mycompany.app/my-app@1",
|
|
||||||
"/packages/php-frontend-3.9.0.6331.jar": "pkg:maven/org.sonarsource.php/php-frontend@3.9.0.6331",
|
"/packages/php-frontend-3.9.0.6331.jar": "pkg:maven/org.sonarsource.php/php-frontend@3.9.0.6331",
|
||||||
"/packages/postgresql-42.5.0.jar": "pkg:maven/org.postgresql/postgresql@42.5.0",
|
"/packages/postgresql-42.5.0.jar": "pkg:maven/org.postgresql/postgresql@42.5.0",
|
||||||
"/packages/protobuf-java-3.21.6.jar": "pkg:maven/com.google.protobuf/protobuf-java@3.21.6",
|
"/packages/protobuf-java-3.21.6.jar": "pkg:maven/com.google.protobuf/protobuf-java@3.21.6",
|
||||||
@@ -532,6 +842,12 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/reactor-netty-http-1.1.9.jar": "pkg:maven/io.projectreactor.netty/reactor-netty-http@1.1.9",
|
"/packages/reactor-netty-http-1.1.9.jar": "pkg:maven/io.projectreactor.netty/reactor-netty-http@1.1.9",
|
||||||
"/packages/reactor-netty-incubator-quic-0.1.3.jar": "pkg:maven/io.projectreactor.netty.incubator/reactor-netty-incubator-quic@0.1.3",
|
"/packages/reactor-netty-incubator-quic-0.1.3.jar": "pkg:maven/io.projectreactor.netty.incubator/reactor-netty-incubator-quic@0.1.3",
|
||||||
"/packages/resilience4j-prometheus-0.17.0.jar": "pkg:maven/io.github.resilience4j.prometheus/resilience4j-prometheus@0.17.0",
|
"/packages/resilience4j-prometheus-0.17.0.jar": "pkg:maven/io.github.resilience4j.prometheus/resilience4j-prometheus@0.17.0",
|
||||||
|
"/packages/script-security.hpi": "pkg:maven/org.jenkins-ci.plugins/script-security@1.74",
|
||||||
|
"/packages/script-security.hpi:WEB-INF/lib/caffeine-2.8.2.jar": "pkg:maven/com.github.ben-manes.caffeine/caffeine@2.8.2",
|
||||||
|
"/packages/script-security.hpi:WEB-INF/lib/checker-qual-3.3.0.jar": "pkg:maven/org.checkerframework.checker.qual/checker-qual@3.3.0",
|
||||||
|
"/packages/script-security.hpi:WEB-INF/lib/error_prone_annotations-2.3.4.jar": "pkg:maven/com.google.errorprone/error_prone_annotations@2.3.4",
|
||||||
|
"/packages/script-security.hpi:WEB-INF/lib/groovy-sandbox-1.26.jar": "pkg:maven/org.kohsuke/groovy-sandbox@1.26",
|
||||||
|
"/packages/script-security.hpi:WEB-INF/lib/script-security.jar": "pkg:maven/org.jenkins-ci.plugins/script-security@1.74",
|
||||||
"/packages/shiro-core-1.9.1.jar": "pkg:maven/org.apache.shiro/shiro-core@1.9.1",
|
"/packages/shiro-core-1.9.1.jar": "pkg:maven/org.apache.shiro/shiro-core@1.9.1",
|
||||||
"/packages/solr-core-8.8.1.jar": "pkg:maven/org.apache.solr/solr-core@8.8.1",
|
"/packages/solr-core-8.8.1.jar": "pkg:maven/org.apache.solr/solr-core@8.8.1",
|
||||||
"/packages/spring-amqp-2.4.17.jar": "pkg:maven/org.springframework.amqp/spring-amqp@2.4.17",
|
"/packages/spring-amqp-2.4.17.jar": "pkg:maven/org.springframework.amqp/spring-amqp@2.4.17",
|
||||||
@@ -557,6 +873,9 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/spring-vault-core-3.0.1.jar": "pkg:maven/org.springframework.vault/spring-vault-core@3.0.1",
|
"/packages/spring-vault-core-3.0.1.jar": "pkg:maven/org.springframework.vault/spring-vault-core@3.0.1",
|
||||||
"/packages/spring-webmvc-3.1.4.RELEASE.jar": "pkg:maven/org.springframework/spring-webmvc@3.1.4.RELEASE",
|
"/packages/spring-webmvc-3.1.4.RELEASE.jar": "pkg:maven/org.springframework/spring-webmvc@3.1.4.RELEASE",
|
||||||
"/packages/spring-xml-3.0.3.RELEASE.jar": "pkg:maven/org.springframework.ws/spring-xml@3.0.3.RELEASE",
|
"/packages/spring-xml-3.0.3.RELEASE.jar": "pkg:maven/org.springframework.ws/spring-xml@3.0.3.RELEASE",
|
||||||
|
"/packages/ssh-credentials.hpi": "pkg:maven/org.jenkins-ci.plugins/ssh-credentials@1.18.1",
|
||||||
|
"/packages/ssh-credentials.hpi:WEB-INF/lib/ssh-credentials.jar": "pkg:maven/org.jenkins-ci.plugins/ssh-credentials@1.18.1",
|
||||||
|
"/packages/storm-core-1.2.2.jar": "pkg:maven/org.apache.storm/storm-core@1.2.2",
|
||||||
"/packages/storm-core-1.2.2.jar:cheshire:cheshire": "pkg:maven/cheshire/cheshire@5.3.1",
|
"/packages/storm-core-1.2.2.jar:cheshire:cheshire": "pkg:maven/cheshire/cheshire@5.3.1",
|
||||||
"/packages/storm-core-1.2.2.jar:clj-time:clj-time": "pkg:maven/clj-time/clj-time@0.8.0",
|
"/packages/storm-core-1.2.2.jar:clj-time:clj-time": "pkg:maven/clj-time/clj-time@0.8.0",
|
||||||
"/packages/storm-core-1.2.2.jar:clout:clout": "pkg:maven/clout/clout@1.2.0",
|
"/packages/storm-core-1.2.2.jar:clout:clout": "pkg:maven/clout/clout@1.2.0",
|
||||||
@@ -606,13 +925,12 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/storm-core-1.2.2.jar:ring:ring-jetty-adapter": "pkg:maven/ring/ring-jetty-adapter@1.3.1",
|
"/packages/storm-core-1.2.2.jar:ring:ring-jetty-adapter": "pkg:maven/ring/ring-jetty-adapter@1.3.1",
|
||||||
"/packages/storm-core-1.2.2.jar:ring:ring-json": "pkg:maven/ring/ring-json@0.3.1",
|
"/packages/storm-core-1.2.2.jar:ring:ring-json": "pkg:maven/ring/ring-json@0.3.1",
|
||||||
"/packages/storm-core-1.2.2.jar:ring:ring-servlet": "pkg:maven/ring/ring-servlet@1.3.1",
|
"/packages/storm-core-1.2.2.jar:ring:ring-servlet": "pkg:maven/ring/ring-servlet@1.3.1",
|
||||||
"/packages/storm-core-1.2.2.jar": "pkg:maven/org.apache.storm/storm-core@1.2.2",
|
|
||||||
"/packages/tapestry-core-5.8.1.jar": "pkg:maven/org.apache.tapestry/tapestry-core@5.8.1",
|
"/packages/tapestry-core-5.8.1.jar": "pkg:maven/org.apache.tapestry/tapestry-core@5.8.1",
|
||||||
"/packages/tika-core-1.26.jar": "pkg:maven/org.apache.tika/tika-core@1.26",
|
"/packages/tika-core-1.26.jar": "pkg:maven/org.apache.tika/tika-core@1.26",
|
||||||
"/packages/tomcat-catalina-11.0.0-M1.jar": "pkg:maven/org.apache.tomcat/tomcat-catalina@11.0.0-M1",
|
"/packages/tomcat-catalina-11.0.0-M1.jar": "pkg:maven/org.apache.tomcat/tomcat-catalina@11.0.0-M1",
|
||||||
"/packages/tomcat-embed-core-11.0.0-M7.jar": "pkg:maven/org.apache.tomcat.embed/tomcat-embed-core@11.0.0-M7",
|
"/packages/tomcat-embed-core-11.0.0-M7.jar": "pkg:maven/org.apache.tomcat.embed/tomcat-embed-core@11.0.0-M7",
|
||||||
|
"/packages/TwilioNotifier.hpi": "pkg:maven/com.twilio.jenkins/TwilioNotifier@0.2.1",
|
||||||
"/packages/TwilioNotifier.hpi:WEB-INF/lib/commons-codec-1.2.jar": "pkg:maven/commons-codec/commons-codec@1.2",
|
"/packages/TwilioNotifier.hpi:WEB-INF/lib/commons-codec-1.2.jar": "pkg:maven/commons-codec/commons-codec@1.2",
|
||||||
"/packages/TwilioNotifier.hpi:WEB-INF/lib/commons-httpclient-3.1.jar": "pkg:maven/org.apache/commons-httpclient@3.1",
|
|
||||||
"/packages/TwilioNotifier.hpi:WEB-INF/lib/commons-logging-1.0.4.jar": "pkg:maven/commons-logging/commons-logging@1.0.4",
|
"/packages/TwilioNotifier.hpi:WEB-INF/lib/commons-logging-1.0.4.jar": "pkg:maven/commons-logging/commons-logging@1.0.4",
|
||||||
"/packages/TwilioNotifier.hpi:WEB-INF/lib/log4j-1.2.9.jar": "pkg:maven/log4j/log4j@1.2.9",
|
"/packages/TwilioNotifier.hpi:WEB-INF/lib/log4j-1.2.9.jar": "pkg:maven/log4j/log4j@1.2.9",
|
||||||
"/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:commons-codec:commons-codec": "pkg:maven/commons-codec/commons-codec@1.4",
|
"/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:commons-codec:commons-codec": "pkg:maven/commons-codec/commons-codec@1.4",
|
||||||
@@ -621,7 +939,6 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:org.apache.httpcomponents:httpclient": "pkg:maven/org.apache.httpcomponents/httpclient@4.1.1",
|
"/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:org.apache.httpcomponents:httpclient": "pkg:maven/org.apache.httpcomponents/httpclient@4.1.1",
|
||||||
"/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:org.apache.httpcomponents:httpcore": "pkg:maven/org.apache.httpcomponents/httpcore@4.1",
|
"/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:org.apache.httpcomponents:httpcore": "pkg:maven/org.apache.httpcomponents/httpcore@4.1",
|
||||||
"/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:org.easymock:easymock": "pkg:maven/org.easymock/easymock@2.4",
|
"/packages/TwilioNotifier.hpi:WEB-INF/lib/sdk-3.0.jar:org.easymock:easymock": "pkg:maven/org.easymock/easymock@2.4",
|
||||||
"/packages/TwilioNotifier.hpi": "pkg:maven/com.twilio.jenkins/TwilioNotifier@0.2.1",
|
|
||||||
"/packages/undertow-core-2.3.4.Final.jar": "pkg:maven/io.undertow/undertow-core@2.3.4.Final",
|
"/packages/undertow-core-2.3.4.Final.jar": "pkg:maven/io.undertow/undertow-core@2.3.4.Final",
|
||||||
"/packages/vaadin-client-8.11.3.jar": "pkg:maven/com.vaadin/vaadin-client@8.11.3",
|
"/packages/vaadin-client-8.11.3.jar": "pkg:maven/com.vaadin/vaadin-client@8.11.3",
|
||||||
"/packages/velocity-1.7.jar": "pkg:maven/org.apache.velocity/velocity@1.7",
|
"/packages/velocity-1.7.jar": "pkg:maven/org.apache.velocity/velocity@1.7",
|
||||||
@@ -629,10 +946,11 @@ var expectedPURLs = map[string]string{
|
|||||||
"/packages/wicket-core-9.2.0.jar": "pkg:maven/org.apache.wicket/wicket-core@9.2.0",
|
"/packages/wicket-core-9.2.0.jar": "pkg:maven/org.apache.wicket/wicket-core@9.2.0",
|
||||||
"/packages/xalan-2.7.2.jar": "pkg:maven/xalan/xalan@2.7.2",
|
"/packages/xalan-2.7.2.jar": "pkg:maven/xalan/xalan@2.7.2",
|
||||||
"/packages/xmlpull-1.1.3.1.jar": "pkg:maven/xmlpull/xmlpull@1.1.3.1",
|
"/packages/xmlpull-1.1.3.1.jar": "pkg:maven/xmlpull/xmlpull@1.1.3.1",
|
||||||
// "/packages/xpp3_min-1.1.4c.jar": "pkg:maven/xpp3/xpp3_min@1.1.4c",
|
|
||||||
"/packages/xstream-1.4.11.1.jar": "pkg:maven/com.thoughtworks.xstream/xstream@1.4.11.1",
|
"/packages/xstream-1.4.11.1.jar": "pkg:maven/com.thoughtworks.xstream/xstream@1.4.11.1",
|
||||||
"/packages/xstream-1.4.19.jar": "pkg:maven/com.thoughtworks.xstream/xstream@1.4.19",
|
"/packages/xstream-1.4.19.jar": "pkg:maven/com.thoughtworks.xstream/xstream@1.4.19",
|
||||||
"/packages/xwiki-commons-xml-15.1.jar": "pkg:maven/org.xwiki.commons/xwiki-commons-xml@15.1",
|
"/packages/xwiki-commons-xml-15.1.jar": "pkg:maven/org.xwiki.commons/xwiki-commons-xml@15.1",
|
||||||
"/packages/xwiki-platform-oldcore-15.3.jar": "pkg:maven/org.xwiki.platform/xwiki-platform-oldcore@15.3",
|
"/packages/xwiki-platform-oldcore-15.3.jar": "pkg:maven/org.xwiki.platform/xwiki-platform-oldcore@15.3",
|
||||||
"/packages/zookeeper-3.7.1.jar": "pkg:maven/org.apache.zookeeper/zookeeper@3.7.1",
|
"/packages/zookeeper-3.7.1.jar": "pkg:maven/org.apache.zookeeper/zookeeper@3.7.1",
|
||||||
|
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar:jline:jline": "pkg:maven/jline/jline@2.11",
|
||||||
|
"/packages/jruby-stdlib-9.1.15.0.jar:META-INF/jruby.home/lib/ruby/stdlib/readline.jar:rubygems:jruby-readline": "pkg:maven/rubygems/jruby-readline@1.2.0",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,8 @@ import (
|
|||||||
func TestMarinerDistroless(t *testing.T) {
|
func TestMarinerDistroless(t *testing.T) {
|
||||||
sbom, _ := catalogFixtureImage(t, "image-mariner-distroless", source.SquashedScope)
|
sbom, _ := catalogFixtureImage(t, "image-mariner-distroless", source.SquashedScope)
|
||||||
|
|
||||||
expectedPkgs := 12
|
// 12 RPMs + 2 binaries with ELF package notes claiming to be RPMs
|
||||||
|
expectedPkgs := 14
|
||||||
actualPkgs := 0
|
actualPkgs := 0
|
||||||
for range sbom.Artifacts.Packages.Enumerate(pkg.RpmPkg) {
|
for range sbom.Artifacts.Packages.Enumerate(pkg.RpmPkg) {
|
||||||
actualPkgs += 1
|
actualPkgs += 1
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func TestNpmPackageLockDirectory(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ensure that integration test commonTestCases stay in sync with the available catalogers
|
// ensure that integration test commonTestCases stay in sync with the available catalogers
|
||||||
const expectedPackageCount = 6
|
const expectedPackageCount = 2
|
||||||
if foundPackages.Size() != expectedPackageCount {
|
if foundPackages.Size() != expectedPackageCount {
|
||||||
t.Errorf("found the wrong set of npm package-lock.json packages (expected: %d, actual: %d)", expectedPackageCount, foundPackages.Size())
|
t.Errorf("found the wrong set of npm package-lock.json packages (expected: %d, actual: %d)", expectedPackageCount, foundPackages.Size())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal/relationship"
|
||||||
"github.com/anchore/syft/syft/artifact"
|
"github.com/anchore/syft/syft/artifact"
|
||||||
"github.com/anchore/syft/syft/source"
|
"github.com/anchore/syft/syft/source"
|
||||||
)
|
)
|
||||||
@@ -44,12 +45,13 @@ func TestBinaryElfRelationships(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
relationshipIndex := relationship.NewIndex(sbom.Relationships...)
|
||||||
for name, expectedDepNames := range expectedGraph {
|
for name, expectedDepNames := range expectedGraph {
|
||||||
pkgId := nameToId[name]
|
pkgId := nameToId[name]
|
||||||
p := sbom.Artifacts.Packages.Package(pkgId)
|
p := sbom.Artifacts.Packages.Package(pkgId)
|
||||||
require.NotNil(t, p, "expected package %q to be present in the SBOM", name)
|
require.NotNil(t, p, "expected package %q to be present in the SBOM", name)
|
||||||
|
|
||||||
rels := sbom.RelationshipsForPackage(*p, artifact.DependencyOfRelationship)
|
rels := relationshipIndex.References(*p, artifact.DependencyOfRelationship)
|
||||||
require.NotEmpty(t, rels, "expected package %q to have relationships", name)
|
require.NotEmpty(t, rels, "expected package %q to have relationships", name)
|
||||||
|
|
||||||
toIds := map[artifact.ID]struct{}{}
|
toIds := map[artifact.ID]struct{}{}
|
||||||
|
|||||||
@@ -52,8 +52,18 @@ func TestAllPackageCatalogersReachableInTasks(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, len(taskTagsByName), constructorCount, "mismatch in number of cataloger constructors and task names")
|
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 {
|
for taskName, tags := range taskTagsByName {
|
||||||
if taskName == "sbom-cataloger" {
|
if exceptions.Has(taskName) {
|
||||||
continue // this is a special case
|
continue // this is a special case
|
||||||
}
|
}
|
||||||
if !strset.New(tags...).HasAny(pkgcataloging.ImageTag, pkgcataloging.DirectoryTag) {
|
if !strset.New(tags...).HasAny(pkgcataloging.ImageTag, pkgcataloging.DirectoryTag) {
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
//go:build !arm64
|
|
||||||
|
|
||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -7,7 +5,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
"github.com/anchore/syft/syft/source"
|
"github.com/anchore/syft/syft/source"
|
||||||
@@ -22,41 +19,39 @@ func TestPackageDeduplication(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
scope: source.AllLayersScope,
|
scope: source.AllLayersScope,
|
||||||
packageCount: 172, // without deduplication this would be 618
|
packageCount: 175, // without deduplication this would be ~600
|
||||||
instanceCount: map[string]int{
|
instanceCount: map[string]int{
|
||||||
"basesystem": 1,
|
"basesystem": 1,
|
||||||
"wget": 1,
|
"wget": 1,
|
||||||
"curl": 2, // upgraded in the image
|
"curl-minimal": 2, // upgraded in the image
|
||||||
"vsftpd": 1,
|
"vsftpd": 1,
|
||||||
"httpd": 1, // rpm, - we exclude binary
|
"httpd": 1, // rpm, - we exclude binary
|
||||||
},
|
},
|
||||||
locationCount: map[string]int{
|
locationCount: map[string]int{
|
||||||
"basesystem-10.0-7.el7.centos": 4,
|
"basesystem-11-13.el9": 5, // in all layers
|
||||||
"curl-7.29.0-59.el7": 1, // from base image
|
"curl-minimal-7.76.1-26.el9_3.2.0.1": 2, // base + wget layer
|
||||||
"curl-7.29.0-59.el7_9.1": 3, // upgrade
|
"curl-minimal-7.76.1-31.el9": 3, // curl upgrade layer + all above layers
|
||||||
"wget-1.14-18.el7_6.1": 3,
|
"wget-1.21.1-8.el9_4": 4, // wget + all above layers
|
||||||
"vsftpd-3.0.2-29.el7_9": 2,
|
"vsftpd-3.0.5-6.el9": 2, // vsftpd + all above layers
|
||||||
"httpd-2.4.6-97.el7.centos.5": 1,
|
"httpd-2.4.62-1.el9_5.2": 1, // last layer
|
||||||
// "httpd-2.4.6": 1, // binary
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scope: source.SquashedScope,
|
scope: source.SquashedScope,
|
||||||
packageCount: 170,
|
packageCount: 169,
|
||||||
instanceCount: map[string]int{
|
instanceCount: map[string]int{
|
||||||
"basesystem": 1,
|
"basesystem": 1,
|
||||||
"wget": 1,
|
"wget": 1,
|
||||||
"curl": 1, // upgraded, but the most recent
|
"curl-minimal": 1, // upgraded, but the most recent
|
||||||
"vsftpd": 1,
|
"vsftpd": 1,
|
||||||
"httpd": 1, // rpm, binary is now excluded by overlap
|
"httpd": 1, // rpm, binary is now excluded by overlap
|
||||||
},
|
},
|
||||||
locationCount: map[string]int{
|
locationCount: map[string]int{
|
||||||
"basesystem-10.0-7.el7.centos": 1,
|
"basesystem-11-13.el9": 1,
|
||||||
"curl-7.29.0-59.el7_9.1": 1, // upgrade
|
"curl-minimal-7.76.1-31.el9": 1, // upgrade
|
||||||
"wget-1.14-18.el7_6.1": 1,
|
"wget-1.21.1-8.el9_4": 1,
|
||||||
"vsftpd-3.0.2-29.el7_9": 1,
|
"vsftpd-3.0.5-6.el9": 1,
|
||||||
"httpd-2.4.6-97.el7.centos.5": 1,
|
"httpd-2.4.62-1.el9_5.2": 1,
|
||||||
// "httpd-2.4.6": 1, // binary (excluded)
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -75,20 +70,21 @@ func TestPackageDeduplication(t *testing.T) {
|
|||||||
pkgs := sbom.Artifacts.Packages.PackagesByName(name)
|
pkgs := sbom.Artifacts.Packages.PackagesByName(name)
|
||||||
|
|
||||||
// with multiple packages with the same name, something is wrong (or this is the wrong fixture)
|
// with multiple packages with the same name, something is wrong (or this is the wrong fixture)
|
||||||
require.Len(t, pkgs, expectedInstanceCount)
|
if assert.Len(t, pkgs, expectedInstanceCount, "unexpected package count for %s", name) {
|
||||||
|
|
||||||
for _, p := range pkgs {
|
for _, p := range pkgs {
|
||||||
nameVersion := fmt.Sprintf("%s-%s", name, p.Version)
|
nameVersion := fmt.Sprintf("%s-%s", name, p.Version)
|
||||||
expectedLocationCount, ok := tt.locationCount[nameVersion]
|
expectedLocationCount, ok := tt.locationCount[nameVersion]
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("missing name-version: %s", nameVersion)
|
t.Errorf("missing name-version: %s", nameVersion)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// we should see merged locations (assumption, there was 1 location for each package)
|
// we should see merged locations (assumption, there was 1 location for each package)
|
||||||
assert.Len(t, p.Locations.ToSlice(), expectedLocationCount)
|
assert.Len(t, p.Locations.ToSlice(), expectedLocationCount, "unexpected location count for %s", nameVersion)
|
||||||
|
|
||||||
// all paths should match
|
// all paths should match
|
||||||
assert.Len(t, p.Locations.CoordinateSet().Paths(), 1)
|
assert.Len(t, p.Locations.CoordinateSet().Paths(), 1, "unexpected location count for %s", nameVersion)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,18 +3,18 @@ package integration
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
"github.com/anchore/syft/syft/source"
|
"github.com/anchore/syft/syft/source"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPhotonPackageRegression(t *testing.T) { // Regression: https://github.com/anchore/syft/pull/1997
|
func TestPhotonPackageRegression(t *testing.T) { // Regression: https://github.com/anchore/syft/pull/1997
|
||||||
sbom, _ := catalogFixtureImage(t, "image-photon-all-layers", source.AllLayersScope)
|
sbom, _ := catalogFixtureImage(t, "image-photon-all-layers", source.AllLayersScope)
|
||||||
var packages []pkg.Package
|
var count int
|
||||||
for p := range sbom.Artifacts.Packages.Enumerate() {
|
for range sbom.Artifacts.Packages.Enumerate(pkg.RpmPkg) {
|
||||||
packages = append(packages, p)
|
count++
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(packages) < 1 {
|
assert.Greater(t, count, 0, "expected to find RPM packages in the SBOM (but did not)")
|
||||||
t.Errorf("failed to find packages for photon distro; wanted > 0 got 0")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/source"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSbomMetadataComponent(t *testing.T) {
|
||||||
|
sbom, _ := catalogFixtureImage(t, "image-sbom-metadata-component", source.SquashedScope, "+sbom-cataloger")
|
||||||
|
|
||||||
|
expectedPkgs := []string{"first-subcomponent", "main-component"}
|
||||||
|
foundPkgs := []string{}
|
||||||
|
|
||||||
|
for sbomPkg := range sbom.Artifacts.Packages.Enumerate(pkg.JavaPkg) {
|
||||||
|
foundPkgs = append(foundPkgs, sbomPkg.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if both the package in `.metadata.component` and the one in `.components` were found
|
||||||
|
if !reflect.DeepEqual(expectedPkgs, foundPkgs) {
|
||||||
|
t.Errorf("expected packages %v, got %v", expectedPkgs, foundPkgs)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,21 @@
|
|||||||
# change these if you want CI to not use previous stored cache
|
FINGERPRINT_FILE := cache.fingerprint
|
||||||
INTEGRATION_CACHE_BUSTER := "894d8ca"
|
|
||||||
|
|
||||||
.PHONY: cache.fingerprint
|
.DEFAULT_GOAL := fixtures
|
||||||
cache.fingerprint:
|
|
||||||
find image-* -type f -exec md5sum {} + | awk '{print $1}' | sort | tee /dev/stderr | md5sum | tee cache.fingerprint && echo "$(INTEGRATION_CACHE_BUSTER)" >> cache.fingerprint
|
# requirement 1: 'fixtures' goal to generate any and all test fixtures
|
||||||
|
fixtures:
|
||||||
|
@echo "nothing to do"
|
||||||
|
|
||||||
|
# requirement 2: 'fingerprint' goal to determine if the fixture input that indicates any existing cache should be busted
|
||||||
|
fingerprint: $(FINGERPRINT_FILE)
|
||||||
|
|
||||||
|
# requirement 3: we always need to recalculate the fingerprint based on source regardless of any existing fingerprint
|
||||||
|
.PHONY: $(FINGERPRINT_FILE)
|
||||||
|
$(FINGERPRINT_FILE):
|
||||||
|
@find image-* -type f -exec sha256sum {} \; | sort -k2 > $(FINGERPRINT_FILE)
|
||||||
|
@#cat $(FINGERPRINT_FILE) | sha256sum | awk '{print $$1}'
|
||||||
|
|
||||||
|
# requirement 4: 'clean' goal to remove all generated test fixtures
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f $(FINGERPRINT_FILE)
|
||||||
|
|||||||
@@ -1 +1,6 @@
|
|||||||
FROM golang:1.18.10-alpine
|
FROM --platform=linux/amd64 golang:1.18.10-alpine
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
# we don't need the entire golang toolchain, just a single binary with the stdlib baked in
|
||||||
|
COPY --from=0 /usr/local/go/bin/gofmt bin/gofmt
|
||||||
|
|||||||
+6
-2
@@ -1,4 +1,4 @@
|
|||||||
FROM jenkins/jenkins:2.346.3-slim-jdk17@sha256:028fbbd9112c60ed086f5197fcba71992317864d27644e5949cf9c52ff4b65f0
|
FROM jenkins/jenkins:2.346.3-slim-jdk17@sha256:028fbbd9112c60ed086f5197fcba71992317864d27644e5949cf9c52ff4b65f0 AS base
|
||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ RUN apt-get update 2>&1 > /dev/null && apt-get install -y less zip 2>&1 > /dev/n
|
|||||||
|
|
||||||
RUN unzip ../jenkins.war 2>&1 > /dev/null
|
RUN unzip ../jenkins.war 2>&1 > /dev/null
|
||||||
|
|
||||||
RUN rm -f ./META-INF/MANIFEST.MF
|
RUN rm -rf ./META-INF/MANIFEST.MF ./WEB-INF ./jsbundles ./scripts ./css
|
||||||
|
|
||||||
WORKDIR /usr/share/jenkins
|
WORKDIR /usr/share/jenkins
|
||||||
|
|
||||||
@@ -21,3 +21,7 @@ RUN rm -rf jenkins.war
|
|||||||
RUN cd ./tmp && zip -r ../jenkins.war . && cd ..
|
RUN cd ./tmp && zip -r ../jenkins.war . && cd ..
|
||||||
|
|
||||||
RUN rm -rf ./tmp
|
RUN rm -rf ./tmp
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
COPY --from=base /usr/share/jenkins/jenkins.war /jenkins.war
|
||||||
|
|||||||
+9
-1
@@ -1,7 +1,15 @@
|
|||||||
FROM alpine:3.18.3@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a
|
FROM alpine:3.18.3@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a AS base
|
||||||
|
|
||||||
RUN wget https://repo1.maven.org/maven2/org/jvnet/hudson/main/hudson-war/2.2.1/hudson-war-2.2.1.war
|
RUN wget https://repo1.maven.org/maven2/org/jvnet/hudson/main/hudson-war/2.2.1/hudson-war-2.2.1.war
|
||||||
|
|
||||||
RUN mv hudson-war-2.2.1.war hudson.war
|
RUN mv hudson-war-2.2.1.war hudson.war
|
||||||
|
|
||||||
|
# let's make this image a little smaller as to not take up so much disk space
|
||||||
|
# we'll only keep the jar metadata files (pom data + manifest) and throw away the rest
|
||||||
|
RUN apk add --no-cache python3 py3-pip
|
||||||
|
COPY extract.py /extract.py
|
||||||
|
RUN python extract.py
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
COPY --from=base /slim /
|
||||||
|
|||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
import os
|
||||||
|
import zipfile
|
||||||
|
import io
|
||||||
|
|
||||||
|
ARCHIVE_EXTENSIONS = ('.jar', '.war', '.ear', '.hpi', '.war', '.sar', '.nar', '.par')
|
||||||
|
METADATA_FILES = ('pom.xml', 'pom.properties', 'MANIFEST.MF')
|
||||||
|
|
||||||
|
|
||||||
|
def slim_archive(archive, output_dir, base_path="", archive_name=""):
|
||||||
|
"""
|
||||||
|
extracts metadata files from the archive and creates a slim JAR file
|
||||||
|
containing only these files. handles nested JARs by preserving them.
|
||||||
|
"""
|
||||||
|
slim_buffer = io.BytesIO()
|
||||||
|
with zipfile.ZipFile(archive, 'r') as zip_file:
|
||||||
|
with zipfile.ZipFile(slim_buffer, 'w', zipfile.ZIP_DEFLATED) as slim_zip:
|
||||||
|
for file_name in zip_file.namelist():
|
||||||
|
# check for metadata files or nested JARs
|
||||||
|
if file_name.endswith(METADATA_FILES):
|
||||||
|
# add metadata files directly to the slimmed archive
|
||||||
|
file_data = zip_file.read(file_name)
|
||||||
|
slim_zip.writestr(file_name, file_data)
|
||||||
|
elif file_name.endswith(ARCHIVE_EXTENSIONS):
|
||||||
|
# if it's a nested archive, recursively slim it
|
||||||
|
nested_archive = io.BytesIO(zip_file.read(file_name))
|
||||||
|
nested_slim_buffer = io.BytesIO()
|
||||||
|
slim_archive(
|
||||||
|
nested_archive,
|
||||||
|
nested_slim_buffer,
|
||||||
|
base_path=os.path.join(base_path, os.path.dirname(file_name)),
|
||||||
|
archive_name=os.path.basename(file_name)
|
||||||
|
)
|
||||||
|
# add the slimmed nested archive back to the parent archive
|
||||||
|
nested_slim_buffer.seek(0)
|
||||||
|
slim_zip.writestr(file_name, nested_slim_buffer.read())
|
||||||
|
|
||||||
|
# write out the slimmed JAR to the output directory if output_dir is a directory
|
||||||
|
if isinstance(output_dir, str):
|
||||||
|
output_path = os.path.join(output_dir, base_path, archive_name)
|
||||||
|
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
||||||
|
with open(output_path, 'wb') as f:
|
||||||
|
slim_buffer.seek(0)
|
||||||
|
f.write(slim_buffer.read())
|
||||||
|
else:
|
||||||
|
# if output_dir is a BytesIO buffer (for nested archives), just write to it
|
||||||
|
output_dir.seek(0)
|
||||||
|
output_dir.write(slim_buffer.getvalue())
|
||||||
|
|
||||||
|
|
||||||
|
def walk_directory_and_slim_jars(base_dir, output_dir):
|
||||||
|
"""
|
||||||
|
recursively walks through a directory tree looking for .jar, .war, .ear,
|
||||||
|
.hpi files and slims them down by keeping only metadata files.
|
||||||
|
"""
|
||||||
|
for dirpath, _, filenames in os.walk(base_dir):
|
||||||
|
for filename in filenames:
|
||||||
|
if filename.endswith(ARCHIVE_EXTENSIONS):
|
||||||
|
archive_path = os.path.join(dirpath, filename)
|
||||||
|
print(f"Processing {archive_path}")
|
||||||
|
slim_archive(archive_path, output_dir, os.path.relpath(dirpath, base_dir), filename)
|
||||||
|
|
||||||
|
|
||||||
|
# a helper script for slimming down JAR files by keeping only metadata files but still keeping the jar packaging,
|
||||||
|
# including nested JARs! Useful for testing purposes.
|
||||||
|
if __name__ == "__main__":
|
||||||
|
BASE_DIR = "."
|
||||||
|
OUTPUT_DIR = "./slim"
|
||||||
|
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||||
|
walk_directory_and_slim_jars(BASE_DIR, OUTPUT_DIR)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine@sha256:d9a7354e3845ea8466bb00b22224d9116b183e594527fb5b6c3d30bc01a20378
|
FROM alpine@sha256:d9a7354e3845ea8466bb00b22224d9116b183e594527fb5b6c3d30bc01a20378 AS base
|
||||||
|
|
||||||
# we keep these unpinned so that if alpine
|
# we keep these unpinned so that if alpine
|
||||||
# changes our integration tests can adapt
|
# changes our integration tests can adapt
|
||||||
@@ -6,3 +6,8 @@ RUN apk add --no-cache \
|
|||||||
tzdata \
|
tzdata \
|
||||||
vim \
|
vim \
|
||||||
alpine-sdk
|
alpine-sdk
|
||||||
|
|
||||||
|
# we don't need the installed bins for this test, only the APK installed metadata
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
COPY --from=base /lib/apk/db/installed /lib/apk/db/installed
|
||||||
|
|||||||
+8
-1
@@ -1 +1,8 @@
|
|||||||
FROM mcr.microsoft.com/cbl-mariner/distroless/base:2.0.202205275@sha256:f550c5428df17b145851ad75983aca6d613ad4b51ca7983b2a83e67d0ac91a5d
|
FROM mcr.microsoft.com/cbl-mariner/distroless/base:2.0.202205275@sha256:f550c5428df17b145851ad75983aca6d613ad4b51ca7983b2a83e67d0ac91a5d AS base
|
||||||
|
|
||||||
|
# let's shoot for smaller test fixtures
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
COPY --from=base /var/lib/rpmmanifest/container-manifest-2 /var/lib/rpmmanifest/container-manifest-2
|
||||||
|
COPY --from=base /usr/bin/gencat /usr/bin/gencat
|
||||||
|
COPY --from=base /usr/bin/openssl /usr/bin/openssl
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba
|
FROM ubuntu:20.04@sha256:33a5cc25d22c45900796a1aca487ad7a7cb09f09ea00b779e3b2026b4fc2faba AS base
|
||||||
# this covers rpm-python
|
# this covers rpm-python
|
||||||
RUN apt-get update && apt-get install -y python-pil=6.2.1-3
|
RUN apt-get update && apt-get install -y python-pil=6.2.1-3
|
||||||
|
|
||||||
|
# let's save some space...
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
COPY --from=base /var/lib/dpkg/status /var/lib/dpkg/status
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
FROM photon:5.0-20230729@sha256:4cf2a1ce0a3f4625f13a0becb6b9bccfdb014c565be6e9a2ec4c4aad1ff8a5d9
|
FROM photon:5.0-20230729@sha256:4cf2a1ce0a3f4625f13a0becb6b9bccfdb014c565be6e9a2ec4c4aad1ff8a5d9 AS base
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
|
COPY --from=base /usr/lib/sysimage/rpm /usr/lib/sysimage/rpm
|
||||||
|
|||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
desc "Advanced Forensic Format"
|
||||||
|
homepage "https://github.com/sshock/AFFLIBv3"
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
opam-version: "2.0"
|
||||||
|
synopsis: "Official release 4.14.0"
|
||||||
|
maintainer: [
|
||||||
|
"David Allsopp <david@tarides.com>"
|
||||||
|
"Florian Angeletti <florian.angeletti@inria.fr>"
|
||||||
|
]
|
||||||
|
authors: "Xavier Leroy and many contributors"
|
||||||
|
license: "LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception"
|
||||||
|
homepage: "https://ocaml.org"
|
||||||
|
bug-reports: "https://github.com/ocaml/opam-repository/issues"
|
||||||
|
depends: [
|
||||||
|
"ocaml" {= "4.14.0" & post}
|
||||||
|
"base-unix" {post}
|
||||||
|
"base-bigarray" {post}
|
||||||
|
"base-threads" {post}
|
||||||
|
"host-arch-arm32" {arch = "arm32" & post}
|
||||||
|
"host-arch-arm64" {arch = "arm64" & post}
|
||||||
|
"host-arch-ppc64" {arch = "ppc64" & post}
|
||||||
|
"host-arch-riscv64" {arch = "riscv64" & post}
|
||||||
|
"host-arch-s390x" {arch = "s390x" & post}
|
||||||
|
"host-arch-x86_32" {os != "win32" & arch = "x86_32" & post}
|
||||||
|
"host-arch-x86_64" {os != "win32" & arch = "x86_64" & post}
|
||||||
|
"host-arch-unknown"
|
||||||
|
{os != "win32" & arch != "arm32" & arch != "arm64" & arch != "ppc64" &
|
||||||
|
arch != "riscv64" &
|
||||||
|
arch != "s390x" &
|
||||||
|
arch != "x86_32" &
|
||||||
|
arch != "x86_64" &
|
||||||
|
post}
|
||||||
|
(("arch-x86_64" {os = "win32" & arch = "x86_64"} &
|
||||||
|
(("system-mingw" & "mingw-w64-shims" {os-distribution = "cygwin" & post}) |
|
||||||
|
"system-msvc")) |
|
||||||
|
("arch-x86_32" {os = "win32"} &
|
||||||
|
(("system-mingw" & "mingw-w64-shims" {os-distribution = "cygwin" & post}) |
|
||||||
|
"system-msvc")) |
|
||||||
|
"host-system-other" {os != "win32" & post})
|
||||||
|
"ocaml-options-vanilla" {post}
|
||||||
|
"flexdll" {>= "0.36" & os = "win32"}
|
||||||
|
]
|
||||||
|
conflict-class: "ocaml-core-compiler"
|
||||||
|
flags: compiler
|
||||||
|
setenv: CAML_LD_LIBRARY_PATH = "%{lib}%/stublibs"
|
||||||
|
build: [
|
||||||
|
[
|
||||||
|
"./configure"
|
||||||
|
"--host=x86_64-pc-windows"
|
||||||
|
{system-msvc:installed & arch-x86_64:installed}
|
||||||
|
"--host=x86_64-w64-mingw32"
|
||||||
|
{os-distribution = "cygwin" & system-mingw:installed &
|
||||||
|
arch-x86_64:installed}
|
||||||
|
"--host=i686-pc-windows" {system-msvc:installed & arch-x86_32:installed}
|
||||||
|
"--host=i686-w64-mingw32"
|
||||||
|
{os-distribution = "cygwin" & system-mingw:installed &
|
||||||
|
arch-x86_32:installed}
|
||||||
|
"--prefix=%{prefix}%"
|
||||||
|
"--docdir=%{doc}%/ocaml"
|
||||||
|
"--with-flexdll=%{flexdll:share}%" {os = "win32" & flexdll:installed}
|
||||||
|
"-C"
|
||||||
|
"CC=cc" {os = "openbsd" | os = "macos"}
|
||||||
|
"ASPP=cc -c" {os = "openbsd" | os = "macos"}
|
||||||
|
]
|
||||||
|
[make "-j%{jobs}%"]
|
||||||
|
]
|
||||||
|
install: [make "install"]
|
||||||
|
build-env: MSYS2_ARG_CONV_EXCL = "*"
|
||||||
|
post-messages: [
|
||||||
|
"""\
|
||||||
|
A failure in the middle of the build may be caused by build parallelism
|
||||||
|
(enabled by default).
|
||||||
|
Please file a bug report at https://github.com/ocaml/opam-repository/issues"""
|
||||||
|
{failure & jobs > "1"}
|
||||||
|
"""\
|
||||||
|
You can try installing again including --jobs=1
|
||||||
|
to force a sequential build instead."""
|
||||||
|
{failure & jobs > "1" & opam-version >= "2.0.5"}
|
||||||
|
]
|
||||||
|
dev-repo: "git+https://github.com/ocaml/ocaml#4.14"
|
||||||
|
url {
|
||||||
|
src: "https://github.com/ocaml/ocaml/archive/4.14.0.tar.gz"
|
||||||
|
checksum:
|
||||||
|
"sha256=39f44260382f28d1054c5f9d8bf4753cb7ad64027da792f7938344544da155e8"
|
||||||
|
}
|
||||||
|
extra-source "ocaml-base-compiler.install" {
|
||||||
|
src:
|
||||||
|
"https://raw.githubusercontent.com/ocaml/opam-source-archives/main/patches/ocaml-base-compiler/ocaml-base-compiler.install"
|
||||||
|
checksum: [
|
||||||
|
"sha256=79f2a1a5044a91350a0eb6ce12e261a72a2855c094c425cddf3860e58c486678"
|
||||||
|
"md5=3e969b841df1f51ca448e6e6295cb451"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
x-env-path-rewrite: [
|
||||||
|
[CAML_LD_LIBRARY_PATH (";" {os = "win32"} ":" {os != "win32"}) "target"]
|
||||||
|
]
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
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";}}
|
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";}}
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -eux
|
set -eux
|
||||||
|
|
||||||
docker create --name generate-rpmdb-fixture centos:latest sh -c 'tail -f /dev/null'
|
docker create --name generate-rpmdb-fixture rockylinux:9 sh -c 'tail -f /dev/null'
|
||||||
|
|
||||||
function cleanup {
|
function cleanup {
|
||||||
docker kill generate-rpmdb-fixture
|
docker kill generate-rpmdb-fixture
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
name(hdt).
|
||||||
|
version('0.5.2').
|
||||||
|
% TODO: swipl_version([90121]).
|
||||||
|
title('Access RDF HDT files').
|
||||||
|
keywords(['RDF']).
|
||||||
|
author( 'Jan Wielemaker', 'J.Wielemaker@vu.nl' ).
|
||||||
|
packager( 'Jan Wielemaker', 'J.Wielemaker@vu.nl' ).
|
||||||
|
maintainer( 'Jan Wielemaker', 'J.Wielemaker@vu.nl' ).
|
||||||
|
home( 'https://github.com/JanWielemaker/hdt' ).
|
||||||
|
download( 'https://github.com/JanWielemaker/hdt/archive/V*.zip' ).
|
||||||
Generated
+25
@@ -0,0 +1,25 @@
|
|||||||
|
# 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",
|
||||||
|
]
|
||||||
|
}
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
FROM scratch
|
||||||
|
COPY test.cdx.json /
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"bomFormat" : "CycloneDX",
|
||||||
|
"specVersion" : "1.5",
|
||||||
|
"serialNumber" : "urn:uuid:dc807d4b-0415-35ab-ba61-49b5d39bc2d9",
|
||||||
|
"version" : 1,
|
||||||
|
"metadata" : {
|
||||||
|
"component" : {
|
||||||
|
"name" : "main-component",
|
||||||
|
"version" : "1.2.3",
|
||||||
|
"purl" : "pkg:maven/org.example/main-component@1.2.3",
|
||||||
|
"type" : "library",
|
||||||
|
"bom-ref" : "pkg:maven/org.example/main-component@1.2.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components" : [
|
||||||
|
{
|
||||||
|
"name" : "first-subcomponent",
|
||||||
|
"version" : "2.3.4",
|
||||||
|
"purl" : "pkg:maven/org.example/first-subcomponent@2.3.4",
|
||||||
|
"type" : "library",
|
||||||
|
"bom-ref" : "pkg:maven/org.example/first-subcomponent@2.3.4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies" : [
|
||||||
|
{
|
||||||
|
"ref" : "pkg:maven/org.example/main-component-assembly@1.2.3",
|
||||||
|
"dependsOn" : [
|
||||||
|
"pkg:maven/org.example/first-subcomponent@2.3.4"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user