github.com/anchore/syft@v1.38.2/Taskfile.yaml (about)

     1  
     2  version: "3"
     3  
     4  includes:
     5    generate:cpe-index: ./task.d/generate/cpe-index.yaml
     6  
     7  vars:
     8    OWNER: anchore
     9    PROJECT: syft
    10  
    11    CACHE_IMAGE: ghcr.io/{{ .OWNER }}/{{ .PROJECT }}/test-fixture-cache:latest
    12  
    13    # static file dirs
    14    TOOL_DIR: .tool
    15    TMP_DIR: .tmp
    16    ORAS_CACHE: "{{ .TMP_DIR }}/oras-cache"
    17    CACHE_PATHS_FILE: "{{ .TMP_DIR }}/cache_paths.json"
    18    LAST_CACHE_PULL_FILE: "{{ .TMP_DIR }}/last_cache_paths.json"
    19  
    20    # TOOLS
    21    ORAS: "{{ .TOOL_DIR }}/oras"
    22    YQ: "{{ .TOOL_DIR }}/yq"
    23    TASK: "{{ .TOOL_DIR }}/task"
    24  
    25    # used for changelog generation
    26    CHANGELOG: CHANGELOG.md
    27    NEXT_VERSION: VERSION
    28  
    29    # used for snapshot builds
    30    OS:
    31      sh: uname -s | tr '[:upper:]' '[:lower:]'
    32    ARCH:
    33      sh: |
    34        [ "$(uname -m)" = "x86_64" ] && echo "amd64_v1" || { [ "$(uname -m)" = "aarch64" ] && echo "arm64_v8.0" || [ "$(uname -m)" = "arm64" ] && echo "arm64_v8.0" || echo $(uname -m); }
    35    PROJECT_ROOT:
    36      sh: echo $PWD
    37  
    38    # note: the snapshot dir must be a relative path starting with ./
    39    # e.g. when installing snapshot debs from a local path, ./ forces the deb to be installed in the current working directory instead of referencing a package name
    40    SNAPSHOT_DIR: ./snapshot
    41    SNAPSHOT_BIN: "{{ .PROJECT_ROOT }}/{{ .SNAPSHOT_DIR }}/{{ .OS }}-build_{{ .OS }}_{{ .ARCH }}/{{ .PROJECT }}"
    42    SNAPSHOT_CMD: "{{ .TOOL_DIR }}/goreleaser release --config {{ .TMP_DIR }}/goreleaser.yaml --clean --snapshot --skip=publish --skip=sign"
    43    BUILD_CMD:    "{{ .TOOL_DIR }}/goreleaser build   --config {{ .TMP_DIR }}/goreleaser.yaml --clean --snapshot --single-target"
    44    RELEASE_CMD:  "{{ .TOOL_DIR }}/goreleaser release --clean --release-notes {{ .CHANGELOG }}"
    45    VERSION:
    46      sh: git describe --dirty --always --tags
    47  
    48    # used for install and acceptance testing
    49    COMPARE_DIR: ./test/compare
    50    COMPARE_TEST_IMAGE: centos:8.2.2004
    51  
    52  env:
    53    GNUMAKEFLAGS: '--no-print-directory'
    54  
    55  tasks:
    56  
    57    ## High-level tasks #################################
    58  
    59    default:
    60      desc: Run all validation tasks
    61      aliases:
    62        - pr-validations
    63        - validations
    64      cmds:
    65        - task: static-analysis
    66        - task: test
    67        - task: install-test
    68  
    69    static-analysis:
    70      desc: Run all static analysis tasks
    71      cmds:
    72        - task: check-go-mod-tidy
    73        - task: check-licenses
    74        - task: lint
    75        - task: check-json-schema-drift
    76        - task: check-binary-fixture-size
    77  
    78    test:
    79      desc: Run all levels of test
    80      cmds:
    81        - task: unit
    82        - task: integration
    83        - task: validate-cyclonedx-schema
    84        - task: test-utils
    85        - task: snapshot
    86        - task: cli
    87        - task: check-docker-cache
    88  
    89    ## Bootstrap tasks #################################
    90  
    91    binny:
    92      internal: true
    93      # desc: Get the binny tool
    94      generates:
    95        - "{{ .TOOL_DIR }}/binny"
    96      status:
    97        - "test -f {{ .TOOL_DIR }}/binny"
    98      cmd: "curl -sSfL https://get.anchore.io/binny | sh -s -- -b .tool"
    99      silent: true
   100  
   101    tools:
   102      desc: Install all tools needed for CI and local development
   103      deps: [binny]
   104      aliases:
   105        - bootstrap
   106      generates:
   107        - ".binny.yaml"
   108        - "{{ .TOOL_DIR }}/*"
   109      status:
   110        - "{{ .TOOL_DIR }}/binny check -v"
   111      cmd: "{{ .TOOL_DIR }}/binny install -v"
   112      silent: true
   113  
   114    update-tools:
   115      desc: Update pinned versions of all tools to their latest available versions
   116      deps: [binny]
   117      generates:
   118        - ".binny.yaml"
   119        - "{{ .TOOL_DIR }}/*"
   120      cmd: "{{ .TOOL_DIR }}/binny update -v"
   121      silent: true
   122  
   123    list-tools:
   124      desc: List all tools needed for CI and local development
   125      deps: [binny]
   126      cmd: "{{ .TOOL_DIR }}/binny list"
   127      silent: true
   128  
   129    list-tool-updates:
   130      desc: List all tools that are not up to date relative to the binny config
   131      deps: [binny]
   132      cmd: "{{ .TOOL_DIR }}/binny list --updates"
   133      silent: true
   134  
   135    tmpdir:
   136      silent: true
   137      generates:
   138        - "{{ .TMP_DIR }}"
   139      cmd: "mkdir -p {{ .TMP_DIR }}"
   140  
   141    ## Static analysis tasks #################################
   142  
   143    format:
   144      desc: Auto-format all source code
   145      deps: [tools]
   146      cmds:
   147        - gofmt -w -s .
   148        - "{{ .TOOL_DIR }}/gosimports -local github.com/anchore -w ."
   149        - go mod tidy
   150  
   151    lint-fix:
   152      desc: Auto-format all source code + run golangci lint fixers
   153      deps: [tools]
   154      cmds:
   155        - task: format
   156        - "{{ .TOOL_DIR }}/golangci-lint run --tests=false --fix"
   157  
   158    lint:
   159      desc: Run gofmt + golangci lint checks
   160      vars:
   161        BAD_FMT_FILES:
   162          sh: gofmt -l -s .
   163        BAD_FILE_NAMES:
   164          sh: "find . | grep -e ':' || true"
   165      deps: [tools]
   166      cmds:
   167        # ensure there are no go fmt differences
   168        - cmd: 'test -z "{{ .BAD_FMT_FILES }}" || (echo "files with gofmt issues: [{{ .BAD_FMT_FILES }}]"; exit 1)'
   169          silent: true
   170        # ensure there are no files with ":" in it (a known back case in the go ecosystem)
   171        - cmd: 'test -z "{{ .BAD_FILE_NAMES }}" || (echo "files with bad names: [{{ .BAD_FILE_NAMES }}]"; exit 1)'
   172          silent: true
   173        # run linting
   174        - "{{ .TOOL_DIR }}/golangci-lint run --tests=false"
   175  
   176  
   177    check-licenses:
   178      # desc: Ensure transitive dependencies are compliant with the current license policy
   179      deps: [tools]
   180      cmd: "{{ .TOOL_DIR }}/bouncer check ./..."
   181  
   182    check-go-mod-tidy:
   183      # desc: Ensure go.mod and go.sum are up to date
   184      cmds:
   185        - cmd: .github/scripts/go-mod-tidy-check.sh && echo "go.mod and go.sum are tidy!"
   186          silent: true
   187  
   188    check-json-schema-drift:
   189      desc: Ensure there is no drift between the JSON schema and the code
   190      cmds:
   191        - .github/scripts/json-schema-drift-check.sh
   192  
   193    check-binary-fixture-size:
   194      desc: Ensure that the binary test fixtures are not too large
   195      cmds:
   196        - .github/scripts/check_binary_fixture_size.sh syft/pkg/cataloger/binary/test-fixtures/classifiers/snippets
   197  
   198  
   199    ## Testing tasks #################################
   200    update-format-golden-files:
   201      desc: "Update golden (i.e. snapshot) files used by unit tests"
   202      cmds:
   203        - go test ./syft/format/spdxjson -update-spdx-json
   204        - go test ./syft/format/spdxtagvalue -update-spdx-tv
   205        - go test ./syft/format/cyclonedxxml -update-cyclonedx-xml
   206        - go test ./syft/format/cyclonedxjson -update-cyclonedx-json
   207        - go test ./syft/format/syftjson -update-json
   208  
   209    unit:
   210      desc: Run unit tests
   211      deps:
   212        - tmpdir
   213        - fixtures
   214      vars:
   215        TEST_PKGS:
   216          sh: "go list ./... | grep -v {{ .OWNER }}/{{ .PROJECT }}/test | grep -v {{ .OWNER }}/{{ .PROJECT }}/cmd/syft/internal/test | tr '\n' ' '"
   217  
   218        # unit test coverage threshold (in % coverage)
   219        COVERAGE_THRESHOLD: 62
   220      cmds:
   221        - "go test -coverprofile {{ .TMP_DIR }}/unit-coverage-details.txt {{ .TEST_PKGS }}"
   222        - cmd: ".github/scripts/coverage.py {{ .COVERAGE_THRESHOLD }} {{ .TMP_DIR }}/unit-coverage-details.txt"
   223          silent: true
   224  
   225    integration:
   226      desc: Run integration tests
   227      cmds:
   228        - "go test -v ./cmd/syft/internal/test/integration"
   229        # exercise most of the CLI with the data race detector
   230        # we use a larger image to ensure we're using multiple catalogers at a time
   231        - "go run -race cmd/syft/main.go anchore/test_images:grype-quality-dotnet-69f15d2"
   232  
   233    validate-cyclonedx-schema:
   234      desc: Validate that Syft produces valid CycloneDX documents
   235      cmds:
   236        - "cd schema/cyclonedx && make"
   237  
   238    cli:
   239      desc: Run CLI tests
   240      deps: [tools]
   241      cmds:
   242        - cmd: "echo 'testing binary: {{ .SNAPSHOT_BIN }}'"
   243          silent: true
   244        - cmd: "test -f {{ .SNAPSHOT_BIN }} || (find {{ .SNAPSHOT_DIR }} && echo '\nno snapshot found for {{ .SNAPSHOT_BIN }}' && false)"
   245          silent: true
   246  
   247        - "go test -count=1 -timeout=15m -v ./test/cli"
   248      env:
   249        SYFT_BINARY_LOCATION: "{{ .SNAPSHOT_BIN }}"
   250  
   251    test-utils:
   252      desc: Run tests for pipeline utils
   253      cmds:
   254        - cmd: .github/scripts/labeler_test.py
   255  
   256  
   257    ## Test-fixture-related targets #################################
   258  
   259    fingerprints:
   260      desc: Generate fingerprints for all non-docker test fixture
   261      silent: true
   262      # this will look for `test-fixtures/Makefile` and invoke the `fingerprint` target to calculate all cache input fingerprint files
   263      generates:
   264        - '**/test-fixtures/**/*.fingerprint'
   265        - test/install/cache.fingerprint
   266      cmds:
   267        - |
   268          BOLD='\033[1m'
   269          YELLOW='\033[0;33m'
   270          RESET='\033[0m'
   271  
   272          echo -e "${YELLOW}creating fingerprint files for non-docker fixtures...${RESET}"
   273          for dir in $(find . -type d -name 'test-fixtures'); do
   274            if [ -f "$dir/Makefile" ]; then
   275              # for debugging...
   276              #echo -e "${YELLOW}• calculating fingerprints in $dir... ${RESET}"
   277  
   278              (make -C "$dir" fingerprint)
   279            fi
   280          done
   281  
   282          # for debugging...
   283          # echo -e "generated all fixture fingerprints"
   284  
   285        - .github/scripts/fingerprint_docker_fixtures.py
   286        - |
   287          # if DOWNLOAD_TEST_FIXTURE_CACHE is set to 'false', then we don't need to calculate the fingerprint for the cache
   288          if [ "$DOWNLOAD_TEST_FIXTURE_CACHE" = "false" ]; then
   289            exit 0
   290          fi
   291          .github/scripts/find_cache_paths.py {{ .CACHE_PATHS_FILE }} > /dev/null
   292  
   293  
   294    refresh-fixtures:
   295      desc: Clear and fetch all test fixture cache
   296      aliases:
   297        - fixtures
   298      silent: true
   299      deps:
   300        - tools
   301      cmds:
   302        - |
   303          BOLD='\033[1m'
   304          PURPLE='\033[0;35m'
   305          RESET='\033[0m'
   306  
   307          # if DOWNLOAD_TEST_FIXTURE_CACHE is set to 'false', then skip the cache download and always build
   308          if [ "$DOWNLOAD_TEST_FIXTURE_CACHE" = "false" ]; then
   309              echo -e "${BOLD}${PURPLE}skipping cache download, rebuilding cache...${RESET}"
   310              {{ .TASK }} build-fixtures
   311              exit 0
   312          fi
   313  
   314          LATEST_FINGERPRINT=$(docker manifest inspect {{ .CACHE_IMAGE }} | {{ .YQ }} -r '.annotations.fingerprint')
   315  
   316          echo "latest cache:      $LATEST_FINGERPRINT"
   317  
   318          if [ -f {{ .LAST_CACHE_PULL_FILE }} ]; then
   319            LAST_PULL_FINGERPRINT=$(cat {{ .LAST_CACHE_PULL_FILE }} | {{ .YQ }} -r '.digest')
   320          else
   321            echo -e "${BOLD}${PURPLE}empty cache, downloading cache...${RESET}"
   322            {{ .TASK }} download-test-fixture-cache
   323            exit 0
   324          fi
   325  
   326          {{ .TASK }} fingerprints
   327  
   328          WANT_FINGERPRINT=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.digest')
   329  
   330          echo "desired cache:     $WANT_FINGERPRINT"
   331          echo "last pulled cache: $LAST_PULL_FINGERPRINT"
   332  
   333          # if we already have the latest cache, skip the refresh
   334          if [ "$LAST_PULL_FINGERPRINT" = "$WANT_FINGERPRINT" ]; then
   335              echo -e "${BOLD}${PURPLE}already have the latest cache (skipping cache download)${RESET}"
   336              exit 0
   337          fi
   338  
   339          # at this point we only refresh the cache if we want the same cache that is currently available.
   340          # we don't by default refresh the cache if the cache if it is simply different from what we have,
   341          # because we may be working on a code change that doesn't require a cache refresh (but could trigger one,
   342          # which would be annoying to deal with in a development workflow).
   343  
   344          if [ "$LATEST_FINGERPRINT" = "$WANT_FINGERPRINT" ]; then
   345            echo -e "${BOLD}${PURPLE}found newer cache! downloading cache...${RESET}"
   346            {{ .TASK }} download-test-fixture-cache
   347          else
   348            echo -e "${BOLD}${PURPLE}found different cache, but isn't clear if it's newer (skipping cache download and manually building)${RESET}"
   349  
   350            {{ .YQ }} eval '.paths[] | "\(.digest) \(.path)"' {{ .LAST_CACHE_PULL_FILE }} > .tmp/last_cache_lines
   351            {{ .YQ }} eval '.paths[] | "\(.digest) \(.path)"' {{ .CACHE_PATHS_FILE }} > .tmp/cache_lines
   352            diff .tmp/last_cache_lines .tmp/cache_lines || true
   353  
   354            echo -e "${BOLD}${PURPLE}diff with more context...${RESET}"
   355  
   356            diff -U10000 {{ .LAST_CACHE_PULL_FILE }} {{ .CACHE_PATHS_FILE }} || true
   357  
   358            echo -e "${BOLD}${PURPLE}detected changes to input material, manually building fixtures...${RESET}"
   359  
   360            {{ .TASK }} build-fixtures
   361          fi
   362  
   363    build-fixtures:
   364      desc: Generate all non-docker test fixtures
   365      silent: true
   366      # this will look for `test-fixtures/Makefile` and invoke the `fixtures` target to generate any and all test fixtures
   367      cmds:
   368        - |
   369          BOLD='\033[1m'
   370          YELLOW='\033[0;33m'
   371          RESET='\033[0m'
   372  
   373          # Use a for loop with command substitution to avoid subshell issues
   374          for dir in $(find . -type d -name 'test-fixtures'); do
   375            if [ -f "$dir/Makefile" ]; then
   376              echo -e "${YELLOW}${BOLD}generating fixtures in $dir${RESET}"
   377              (make -C "$dir" fixtures)
   378            fi
   379          done
   380          echo -e "${BOLD}generated all fixtures${RESET}"
   381  
   382    download-test-fixture-cache:
   383      desc: Download test fixture cache from ghcr.io
   384      deps: [tools, clean-cache]
   385      vars:
   386        CACHE_DIGEST:
   387          sh: docker manifest inspect {{ .CACHE_IMAGE }} | {{ .YQ }} -r '.annotations.fingerprint'
   388      cmds:
   389        - silent: true
   390          cmd: |
   391            # if oras cache is > 4 GB, delete it
   392            if [ -d {{ .ORAS_CACHE }} ]; then
   393              total_size=$(du -c {{ .ORAS_CACHE }} | grep total | awk '{print $1}')
   394              if [ "$total_size" -gt 4194304 ]; then
   395                echo 'deleting oras cache'
   396                rm -rf {{ .ORAS_CACHE }}
   397              fi
   398            fi
   399        - "ORAS_CACHE={{ .ORAS_CACHE }} {{ .ORAS }} pull {{ .CACHE_IMAGE }}"
   400        - "cp {{ .CACHE_PATHS_FILE }} {{ .LAST_CACHE_PULL_FILE }}"
   401  
   402    upload-test-fixture-cache:
   403      desc: Upload the test fixture cache to ghcr.io
   404      deps: [tools, fingerprints]
   405      silent: true
   406      cmd: |
   407        set -eu
   408        oras_command="{{ .ORAS }} push {{ .CACHE_IMAGE }}"
   409  
   410        paths=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.paths[].path')
   411        for path in $paths; do
   412          oras_command+=" $path"
   413        done
   414        oras_command+=" {{ .CACHE_PATHS_FILE }}"
   415  
   416        oras_command+=" --annotation org.opencontainers.image.source=https://github.com/{{ .OWNER }}/{{ .PROJECT }}"
   417        oras_command+=" --annotation fingerprint=$(cat {{ .CACHE_PATHS_FILE }} | {{ .YQ }} -r '.digest')"
   418  
   419        echo "Executing: $oras_command"
   420        eval $oras_command
   421  
   422    show-test-image-cache:
   423      silent: true
   424      cmds:
   425        - "echo 'Docker daemon cache:'"
   426        - "docker images --format '{{`{{.ID}}`}} {{`{{.Repository}}`}}:{{`{{.Tag}}`}}' | grep stereoscope-fixture- | sort"
   427        - "echo '\nTar cache:'"
   428        - 'find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" | sort'
   429  
   430    check-docker-cache:
   431      desc: Ensure docker caches aren't using too much disk space
   432      silent: true
   433      cmd: |
   434        total_size=$(find . | grep cache | grep tar | xargs du -c | grep total | awk '{print $1}')
   435        find . | grep cache | grep tar | xargs du
   436        echo "total $total_size KB"
   437  
   438        if [ "$total_size" -gt 5242880  ]; then
   439          echo 'docker cache is larger than 5GB'
   440          exit 1
   441        fi
   442  
   443    ## install.sh testing targets #################################
   444  
   445    install-test:
   446      cmds:
   447        - "cd test/install && make"
   448  
   449    install-test-cache-save:
   450      cmds:
   451        - "cd test/install && make save"
   452  
   453    install-test-cache-load:
   454      cmds:
   455        - "cd test/install && make load"
   456  
   457    install-test-ci-mac:
   458      cmds:
   459        - "cd test/install && make ci-test-mac"
   460  
   461    generate-compare-file:
   462      cmd: "go run ./cmd/syft {{ .COMPARE_TEST_IMAGE }} -o json > {{ .COMPARE_DIR }}/test-fixtures/acceptance-{{ .COMPARE_TEST_IMAGE }}.json"
   463  
   464    compare-mac:
   465      deps: [tmpdir]
   466      cmd: |
   467        {{ .COMPARE_DIR }}/mac.sh \
   468          {{ .SNAPSHOT_DIR }} \
   469          {{ .COMPARE_DIR }} \
   470          {{ .COMPARE_TEST_IMAGE }} \
   471          {{ .TMP_DIR }}
   472  
   473    compare-linux:
   474      cmds:
   475        - task: compare-test-deb-package-install
   476        - task: compare-test-rpm-package-install
   477  
   478    compare-test-deb-package-install:
   479      deps: [tmpdir]
   480      cmd: |
   481        {{ .COMPARE_DIR }}/deb.sh \
   482          {{ .SNAPSHOT_DIR }} \
   483          {{ .COMPARE_DIR }} \
   484          {{ .COMPARE_TEST_IMAGE }} \
   485          {{ .TMP_DIR }}
   486  
   487    compare-test-rpm-package-install:
   488      deps: [tmpdir]
   489      cmd: |
   490        {{ .COMPARE_DIR }}/rpm.sh \
   491          {{ .SNAPSHOT_DIR }} \
   492          {{ .COMPARE_DIR }} \
   493          {{ .COMPARE_TEST_IMAGE }} \
   494          {{ .TMP_DIR }}
   495  
   496  
   497    ## Code and data generation targets #################################
   498  
   499    generate:
   500      desc: Add data generation tasks
   501      cmds:
   502        - task: generate-json-schema
   503        - task: generate-license-list
   504        - task: generate-cpe-dictionary-index
   505  
   506    generate-json-schema:
   507      desc: Generate a new JSON schema
   508      cmds:
   509        - "cd ./internal && go generate . && cd ./jsonschema && go run . && go fmt ../..."
   510  
   511    generate-license-list:
   512      desc: Generate an updated license processing code off of the latest available SPDX license list
   513      cmds:
   514        - "go generate ./internal/spdxlicense/..."
   515        - "gofmt -s -w ./internal/spdxlicense"
   516  
   517    generate-cpe-dictionary-index:
   518      desc: Generate the CPE index from local cache
   519      cmds:
   520        - task: generate:cpe-index:cache:pull
   521        - task: generate:cpe-index:cache:update
   522        - task: generate:cpe-index:build
   523  
   524  
   525    ## Build-related targets #################################
   526  
   527    build:
   528      desc: Build the project
   529      deps: [tools, tmpdir]
   530      generates:
   531        - "{{ .PROJECT }}"
   532      cmds:
   533        - silent: true
   534          cmd: |
   535            echo "dist: {{ .SNAPSHOT_DIR }}" > {{ .TMP_DIR }}/goreleaser.yaml
   536            cat .goreleaser.yaml >> {{ .TMP_DIR }}/goreleaser.yaml
   537  
   538        - "{{ .BUILD_CMD }}"
   539  
   540    snapshot:
   541      desc: Create a snapshot release
   542      aliases:
   543        - build
   544      deps: [tools, tmpdir]
   545      sources:
   546        - cmd/**/*.go
   547        - syft/**/*.go
   548        - internal/**/*.go
   549      method: checksum
   550      generates:
   551        - "{{ .SNAPSHOT_BIN }}"
   552      cmds:
   553        - silent: true
   554          cmd: |
   555            echo "dist: {{ .SNAPSHOT_DIR }}" > {{ .TMP_DIR }}/goreleaser.yaml
   556            cat .goreleaser.yaml >> {{ .TMP_DIR }}/goreleaser.yaml
   557  
   558        - "{{ .SNAPSHOT_CMD }}"
   559  
   560    snapshot-smoke-test:
   561      desc: Run a smoke test on the snapshot builds + docker images
   562      cmds:
   563        - cmd: "echo 'testing snapshot binary: {{ .SNAPSHOT_BIN }}'"
   564          silent: true
   565        - cmd: "test -f {{ .SNAPSHOT_BIN }} || (find {{ .SNAPSHOT_DIR }} && echo '\nno snapshot found for {{ .SNAPSHOT_BIN }}' && false)"
   566          silent: true
   567        - "{{ .SNAPSHOT_BIN }} version"
   568        - "{{ .SNAPSHOT_BIN }} scan alpine:latest"
   569        - docker run --rm anchore/syft:latest version
   570        - docker run --rm anchore/syft:latest scan alpine:latest
   571  
   572    changelog:
   573      desc: Generate a changelog
   574      deps: [tools]
   575      generates:
   576        - "{{ .CHANGELOG }}"
   577        - "{{ .NEXT_VERSION }}"
   578      cmds:
   579        - "{{ .TOOL_DIR }}/chronicle -vv -n --version-file {{ .NEXT_VERSION }} > {{ .CHANGELOG }}"
   580        - "{{ .TOOL_DIR }}/glow -w 0 {{ .CHANGELOG }}"
   581  
   582  
   583    ## Release targets #################################
   584  
   585    release:
   586      desc: Create a release
   587      interactive: true
   588      deps: [tools]
   589      cmds:
   590        - cmd: .github/scripts/trigger-release.sh
   591          silent: true
   592  
   593  
   594    ## CI-only targets #################################
   595  
   596    ci-check:
   597      # desc: "[CI only] Are you in CI?"
   598      cmds:
   599        - cmd: .github/scripts/ci-check.sh
   600          silent: true
   601  
   602    ci-release:
   603      # desc: "[CI only] Create a release"
   604      deps: [tools]
   605      cmds:
   606        - task: ci-check
   607        - "{{ .TOOL_DIR }}/chronicle -vvv > CHANGELOG.md"
   608        - cmd: "cat CHANGELOG.md"
   609          silent: true
   610        - "{{ .RELEASE_CMD }}"
   611  
   612  
   613    ## Cleanup targets #################################
   614  
   615    clean-snapshot:
   616      desc: Remove any snapshot builds
   617      cmds:
   618        - "rm -rf {{ .SNAPSHOT_DIR }}"
   619        - "rm -rf {{ .TMP_DIR }}/goreleaser.yaml"
   620  
   621    clean-docker-cache:
   622      desc: Remove all docker cache tars and images from the daemon
   623      cmds:
   624        - find . -type d -wholename "**/test-fixtures/cache" | xargs rm -rf
   625        - docker images --format '{{`{{.ID}}`}} {{`{{.Repository}}`}}' | grep stereoscope-fixture- | awk '{print $1}' | uniq | xargs -r docker rmi --force
   626  
   627    clean-oras-cache:
   628      desc: Remove all cache for oras commands
   629      cmd: rm -rf {{ .ORAS_CACHE }}
   630  
   631    clean-cache:
   632      desc: Remove all image docker tar cache, images from the docker daemon, and ephemeral test fixtures
   633      cmds:
   634        - task: clean-docker-cache
   635        - |
   636          BOLD='\033[1m'
   637          YELLOW='\033[0;33m'
   638          RESET='\033[0m'
   639  
   640          # Use a for loop with command substitution to avoid subshell issues
   641          for dir in $(find . -type d -name 'test-fixtures'); do
   642          if [ -f "$dir/Makefile" ]; then
   643            echo -e "${YELLOW}${BOLD}deleting ephemeral test fixtures in $dir${RESET}"
   644            (make -C "$dir" clean)
   645          fi
   646          done
   647          echo -e "${BOLD}Deleted all ephemeral test fixtures${RESET}"
   648        - rm -f {{ .LAST_CACHE_PULL_FILE }} {{ .CACHE_PATHS_FILE }}