mirror of
https://github.com/wagoodman/dive
synced 2026-03-14 14:25:50 +01:00
upd scripts and readme
This commit is contained in:
parent
3465d86d21
commit
2b06350f02
10 changed files with 292 additions and 202 deletions
BIN
.data/demo.gif
BIN
.data/demo.gif
Binary file not shown.
|
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 2 MiB |
73
.github/workflows/release.yaml
vendored
73
.github/workflows/release.yaml
vendored
|
|
@ -24,7 +24,6 @@ jobs:
|
|||
id: static-analysis
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# This check name is defined as the github action job name (in .github/workflows/validations.yaml)
|
||||
checkName: "Static analysis"
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
|
|
@ -33,55 +32,21 @@ jobs:
|
|||
id: unit
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# This check name is defined as the github action job name (in .github/workflows/validations.yaml)
|
||||
checkName: "Unit tests (ubuntu-latest)"
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Check acceptance test results (linux)
|
||||
uses: fountainhead/action-wait-for-check@v1.2.0
|
||||
id: acceptance-linux
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# This check name is defined as the github action job name (in .github/workflows/validations.yaml)
|
||||
checkName: "Acceptance tests (Linux)"
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Check acceptance test results (mac)
|
||||
uses: fountainhead/action-wait-for-check@v1.2.0
|
||||
id: acceptance-mac
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# This check name is defined as the github action job name (in .github/workflows/validations.yaml)
|
||||
checkName: "Acceptance tests (Mac)"
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Check acceptance test results (windows)
|
||||
uses: fountainhead/action-wait-for-check@v1.2.0
|
||||
id: acceptance-windows
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# This check name is defined as the github action job name (in .github/workflows/validations.yaml)
|
||||
checkName: "Acceptance tests (Windows)"
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Quality gate
|
||||
if: steps.static-analysis.outputs.conclusion != 'success' || steps.unit.outputs.conclusion != 'success' || steps.acceptance-linux.outputs.conclusion != 'success' || steps.acceptance-mac.outputs.conclusion != 'success' || steps.acceptance-windows.outputs.conclusion != 'success'
|
||||
if: steps.static-analysis.outputs.conclusion != 'success' || steps.unit.outputs.conclusion != 'success'
|
||||
run: |
|
||||
echo "Static Analysis Status: ${{ steps.static-analysis.conclusion }}"
|
||||
echo "Unit Test Status: ${{ steps.unit.outputs.conclusion }}"
|
||||
echo "Acceptance Test (Linux) Status: ${{ steps.acceptance-linux.outputs.conclusion }}"
|
||||
echo "Acceptance Test (Mac) Status: ${{ steps.acceptance-mac.outputs.conclusion }}"
|
||||
echo "Acceptance Test (Windows) Status: ${{ steps.acceptance-windows.outputs.conclusion }}"
|
||||
|
||||
false
|
||||
|
||||
release:
|
||||
needs: [quality-gate]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# for tagging
|
||||
contents: write
|
||||
# for pushing container images
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
@ -91,15 +56,8 @@ jobs:
|
|||
- name: Bootstrap environment
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 #v3.4.0
|
||||
with:
|
||||
registry: docker.io
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 #v3.4.0
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
@ -121,10 +79,27 @@ jobs:
|
|||
- name: Build & publish release artifacts
|
||||
run: make ci-release
|
||||
env:
|
||||
# for creating the release (requires write access to content)
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# for updating brew formula in wagoodman/homebrew-dive
|
||||
TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }}
|
||||
|
||||
- name: Smoke test published image
|
||||
run: make ci-test-docker-image
|
||||
npm-publish:
|
||||
needs: [release]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Update package.json version
|
||||
run: |
|
||||
VERSION="${{ github.event.inputs.version }}"
|
||||
VERSION="${VERSION#v}"
|
||||
npm version $VERSION --no-git-tag-version
|
||||
|
||||
- name: Publish to npm
|
||||
run: npm publish --access public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
|
|
|||
22
.github/workflows/validations.yaml
vendored
22
.github/workflows/validations.yaml
vendored
|
|
@ -8,7 +8,6 @@ on:
|
|||
|
||||
jobs:
|
||||
Static-Analysis:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Static analysis"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
|
@ -21,15 +20,11 @@ jobs:
|
|||
run: make static-analysis
|
||||
|
||||
Unit-Test:
|
||||
# Note: changing this job name requires making the same update in the .github/workflows/release.yaml pipeline
|
||||
name: "Unit tests"
|
||||
strategy:
|
||||
matrix:
|
||||
platform:
|
||||
- ubuntu-latest
|
||||
# - macos-latest # todo: mac runners are expensive minute-wise
|
||||
# - windows-latest # todo: support windows
|
||||
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
@ -58,25 +53,16 @@ jobs:
|
|||
- name: Build snapshot artifacts
|
||||
run: make snapshot
|
||||
|
||||
- run: docker images wagoodman/dive
|
||||
|
||||
# todo: compare against known json output in shared volume
|
||||
- name: Test production image
|
||||
run: make ci-test-docker-image
|
||||
|
||||
# why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach).
|
||||
# see https://github.com/actions/upload-artifact/issues/199 for more info
|
||||
- name: Upload snapshot artifacts
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: snapshot
|
||||
key: snapshot-build-${{ github.run_id }}
|
||||
|
||||
# ... however the cache trick doesn't work on windows :(
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows-artifacts
|
||||
path: snapshot/dive_windows_amd64_v1/dive.exe
|
||||
path: snapshot/superdive_windows_amd64_v1/superdive.exe
|
||||
|
||||
Acceptance-Linux:
|
||||
name: "Acceptance tests (Linux)"
|
||||
|
|
@ -94,12 +80,6 @@ jobs:
|
|||
- name: Test linux run
|
||||
run: make ci-test-linux-run
|
||||
|
||||
- name: Test DEB package installation
|
||||
run: make ci-test-deb-package-install
|
||||
|
||||
- name: Test RPM package installation
|
||||
run: make ci-test-rpm-package-install
|
||||
|
||||
Acceptance-Mac:
|
||||
name: "Acceptance tests (Mac)"
|
||||
needs: [Build-Snapshot-Artifacts]
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ env:
|
|||
- CGO_ENABLED=0
|
||||
|
||||
builds:
|
||||
- binary: dive
|
||||
- id: superdive
|
||||
binary: superdive
|
||||
dir: ./cmd/dive
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
|
|
@ -25,7 +26,6 @@ builds:
|
|||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
- ppc64le
|
||||
ldflags:
|
||||
-w
|
||||
-s
|
||||
|
|
@ -35,40 +35,35 @@ builds:
|
|||
-X main.buildDate={{.Date}}
|
||||
-X main.gitDescription={{.Summary}}
|
||||
|
||||
brews:
|
||||
- repository:
|
||||
owner: wagoodman
|
||||
name: homebrew-dive
|
||||
token: "{{.Env.TAP_GITHUB_TOKEN}}"
|
||||
homepage: &project_url "https://github.com/wagoodman/dive/"
|
||||
description: &description "A tool for exploring layers in a docker image"
|
||||
|
||||
archives:
|
||||
- format: tar.gz
|
||||
- id: superdive-archives
|
||||
builds:
|
||||
- superdive
|
||||
name_template: "superdive_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||
format: tar.gz
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
|
||||
nfpms:
|
||||
- license: MIT
|
||||
maintainer: Alex Goodman
|
||||
homepage: *project_url
|
||||
description: *description
|
||||
maintainer: Aslan Dukaev
|
||||
homepage: "https://github.com/dukaev/superdive"
|
||||
description: "A tool for exploring layers in a docker image"
|
||||
formats:
|
||||
- rpm
|
||||
- deb
|
||||
|
||||
dockers:
|
||||
# docker.io amd64
|
||||
- &dockerhub_amd64
|
||||
- &docker_amd64
|
||||
id: docker-amd64
|
||||
ids:
|
||||
- dive
|
||||
- superdive
|
||||
use: buildx
|
||||
goarch: amd64
|
||||
image_templates:
|
||||
- docker.io/wagoodman/dive:latest
|
||||
- docker.io/wagoodman/dive:v{{.Version}}-amd64
|
||||
- ghcr.io/dukaev/superdive:latest
|
||||
- ghcr.io/dukaev/superdive:v{{.Version}}-amd64
|
||||
build_flag_templates:
|
||||
- "--build-arg=DOCKER_CLI_VERSION={{.Env.DOCKER_CLI_VERSION}}"
|
||||
- "--platform=linux/amd64"
|
||||
|
|
@ -80,17 +75,15 @@ dockers:
|
|||
- "--label=org.opencontainers.image.version={{.Version}}"
|
||||
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
|
||||
- "--label=org.opencontainers.image.licenses=MIT"
|
||||
- "--label=org.opencontainers.image.authors=Alex Goodman <@wagoodman>"
|
||||
|
||||
# docker.io arm64
|
||||
- &dockerhub_arm64
|
||||
- &docker_arm64
|
||||
id: docker-arm64
|
||||
ids:
|
||||
- dive
|
||||
- superdive
|
||||
use: buildx
|
||||
goarch: arm64
|
||||
image_templates:
|
||||
- docker.io/wagoodman/dive:v{{.Version}}-arm64
|
||||
- ghcr.io/dukaev/superdive:v{{.Version}}-arm64
|
||||
build_flag_templates:
|
||||
- "--build-arg=DOCKER_CLI_VERSION={{.Env.DOCKER_CLI_VERSION}}"
|
||||
- "--platform=linux/arm64/v8"
|
||||
|
|
@ -102,47 +95,14 @@ dockers:
|
|||
- "--label=org.opencontainers.image.version={{.Version}}"
|
||||
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
|
||||
- "--label=org.opencontainers.image.licenses=MIT"
|
||||
- "--label=org.opencontainers.image.authors=Alex Goodman <@wagoodman>"
|
||||
|
||||
# ghcr.io amd64
|
||||
- id: ghcr-amd64
|
||||
<<: *dockerhub_amd64
|
||||
image_templates:
|
||||
- ghcr.io/wagoodman/dive:v{{.Version}}-amd64
|
||||
|
||||
# ghcr.io arm64
|
||||
- id: ghcr-arm64
|
||||
<<: *dockerhub_arm64
|
||||
image_templates:
|
||||
- ghcr.io/wagoodman/dive:v{{.Version}}-arm64
|
||||
|
||||
docker_manifests:
|
||||
# docker.io manifests
|
||||
- name_template: docker.io/wagoodman/dive:latest
|
||||
image_templates: &dockerhub_images
|
||||
- docker.io/wagoodman/dive:v{{.Version}}-amd64
|
||||
- docker.io/wagoodman/dive:v{{.Version}}-arm64
|
||||
- name_template: ghcr.io/dukaev/superdive:latest
|
||||
image_templates:
|
||||
- ghcr.io/dukaev/superdive:v{{.Version}}-amd64
|
||||
- ghcr.io/dukaev/superdive:v{{.Version}}-arm64
|
||||
|
||||
- name_template: docker.io/wagoodman/dive:v{{.Major}}
|
||||
image_templates: *dockerhub_images
|
||||
|
||||
- name_template: docker.io/wagoodman/dive:v{{.Major}}.{{.Minor}}
|
||||
image_templates: *dockerhub_images
|
||||
|
||||
- name_template: docker.io/wagoodman/dive:v{{.Version}}
|
||||
image_templates: *dockerhub_images
|
||||
|
||||
# ghcr.io manifests
|
||||
- name_template: ghcr.io/wagoodman/dive:latest
|
||||
image_templates: &ghcr_images
|
||||
- ghcr.io/wagoodman/dive:v{{.Version}}-amd64
|
||||
- ghcr.io/wagoodman/dive:v{{.Version}}-arm64
|
||||
|
||||
- name_template: ghcr.io/wagoodman/dive:v{{.Major}}
|
||||
image_templates: *ghcr_images
|
||||
|
||||
- name_template: ghcr.io/wagoodman/dive:v{{.Major}}.{{.Minor}}
|
||||
image_templates: *ghcr_images
|
||||
|
||||
- name_template: ghcr.io/wagoodman/dive:v{{.Version}}
|
||||
image_templates: *ghcr_images
|
||||
- name_template: ghcr.io/dukaev/superdive:v{{.Version}}
|
||||
image_templates:
|
||||
- ghcr.io/dukaev/superdive:v{{.Version}}-amd64
|
||||
- ghcr.io/dukaev/superdive:v{{.Version}}-arm64
|
||||
|
|
|
|||
38
.npmignore
Normal file
38
.npmignore
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# Source files
|
||||
cmd/
|
||||
dive/
|
||||
internal/
|
||||
*.go
|
||||
go.mod
|
||||
go.sum
|
||||
|
||||
# Build files
|
||||
Makefile
|
||||
Taskfile.yaml
|
||||
Dockerfile
|
||||
.goreleaser.yaml
|
||||
.golangci.yaml
|
||||
coverage.out
|
||||
snapshot/
|
||||
|
||||
# Git/GitHub
|
||||
.git/
|
||||
.github/
|
||||
.gitignore
|
||||
|
||||
# Config files
|
||||
.binny.yaml
|
||||
.bouncer.yaml
|
||||
.dockerignore
|
||||
.dive-ci
|
||||
|
||||
# Documentation (keep README)
|
||||
RELEASE.md
|
||||
AGENTS.md
|
||||
|
||||
# Data
|
||||
.data/
|
||||
|
||||
# Test files
|
||||
*_test.go
|
||||
testdata/
|
||||
6
Makefile
6
Makefile
|
|
@ -1,5 +1,5 @@
|
|||
OWNER = wagoodman
|
||||
PROJECT = dive
|
||||
OWNER = dukaev
|
||||
PROJECT = superdive
|
||||
|
||||
TOOL_DIR = .tool
|
||||
BINNY = $(TOOL_DIR)/binny
|
||||
|
|
@ -41,7 +41,7 @@ $(TASKS): $(TASK)
|
|||
## actual targets
|
||||
|
||||
ci-test-windows-run:
|
||||
dive.exe --source docker-archive .data/test-docker-image.tar --ci --ci-config .data/.dive-ci
|
||||
superdive.exe --source docker-archive .data/test-docker-image.tar --ci --ci-config .data/.dive-ci
|
||||
|
||||
help: $(TASK)
|
||||
@$(TASK) -l
|
||||
|
|
|
|||
80
README.md
80
README.md
|
|
@ -2,47 +2,41 @@
|
|||
|
||||
**A tool for exploring a Docker image, layer contents, and discovering ways to shrink the size of your Docker/OCI image.**
|
||||
|
||||
|
||||

|
||||
|
||||
To analyze a Docker image simply run dive with an image tag/id/digest:
|
||||
```bash
|
||||
dive <your-image-tag>
|
||||
```
|
||||
## Installation
|
||||
|
||||
or you can dive with Docker directly:
|
||||
```
|
||||
alias dive="docker run -ti --rm -v /var/run/docker.sock:/var/run/docker.sock docker.io/wagoodman/dive"
|
||||
dive <your-image-tag>
|
||||
|
||||
# for example
|
||||
dive nginx:latest
|
||||
```
|
||||
|
||||
or if you want to build your image then jump straight into analyzing it:
|
||||
```bash
|
||||
dive build -t <some-tag> .
|
||||
```
|
||||
|
||||
Building on macOS (supporting only the Docker container engine):
|
||||
### bun/npm (recommended)
|
||||
|
||||
```bash
|
||||
docker run --rm -it \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v "$(pwd)":"$(pwd)" \
|
||||
-w "$(pwd)" \
|
||||
-v "$HOME/.dive.yaml":"$HOME/.dive.yaml" \
|
||||
docker.io/wagoodman/dive:latest build -t <some-tag> .
|
||||
bun install -g superdive
|
||||
npm install -g superdive
|
||||
```
|
||||
|
||||
### From source
|
||||
|
||||
```bash
|
||||
git clone https://github.com/dukaev/superdive.git
|
||||
cd superdive
|
||||
go build -o superdive ./cmd/dive
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
To analyze a Docker image simply run superdive with an image tag/id/digest:
|
||||
```bash
|
||||
superdive <your-image-tag>
|
||||
```
|
||||
|
||||
Or if you want to build your image then jump straight into analyzing it:
|
||||
```bash
|
||||
superdive build -t <some-tag> .
|
||||
```
|
||||
|
||||
Additionally you can run this in your CI pipeline to ensure you're keeping wasted space to a minimum (this skips the UI):
|
||||
```bash
|
||||
CI=true superdive <your-image>
|
||||
```
|
||||
CI=true dive <your-image>
|
||||
```
|
||||
|
||||

|
||||
|
||||
**This is beta quality!** *Feel free to submit an issue if you want a new feature or find a bug :)*
|
||||
|
||||
## Basic Features
|
||||
|
||||
|
|
@ -61,24 +55,25 @@ The lower left pane shows basic layer info and an experimental metric that will
|
|||
**Quick build/analysis cycles**
|
||||
|
||||
You can build a Docker image and do an immediate analysis with one command:
|
||||
`dive build -t some-tag .`
|
||||
```bash
|
||||
superdive build -t some-tag .
|
||||
```
|
||||
|
||||
You only need to replace your `docker build` command with the same `dive build`
|
||||
command.
|
||||
You only need to replace your `docker build` command with the same `superdive build` command.
|
||||
|
||||
**CI Integration**
|
||||
|
||||
Analyze an image and get a pass/fail result based on the image efficiency and wasted space. Simply set `CI=true` in the environment when invoking any valid dive command.
|
||||
Analyze an image and get a pass/fail result based on the image efficiency and wasted space. Simply set `CI=true` in the environment when invoking any valid superdive command.
|
||||
|
||||
**Multiple Image Sources and Container Engines Supported**
|
||||
|
||||
With the `--source` option, you can select where to fetch the container image from:
|
||||
```bash
|
||||
dive <your-image> --source <source>
|
||||
superdive <your-image> --source <source>
|
||||
```
|
||||
or
|
||||
```bash
|
||||
dive <source>://<your-image>
|
||||
superdive <source>://<your-image>
|
||||
```
|
||||
|
||||
With valid `source` options as such:
|
||||
|
|
@ -86,11 +81,10 @@ With valid `source` options as such:
|
|||
- `docker-archive`: A Docker Tar Archive from disk
|
||||
- `podman`: Podman engine (linux only)
|
||||
|
||||
|
||||
## CI Integration
|
||||
|
||||
When running dive with the environment variable `CI=true` then the dive UI will be bypassed and will instead analyze your docker image, giving it a pass/fail indication via return code. Currently there are three metrics supported via a `.dive-ci` file that you can put at the root of your repo:
|
||||
```
|
||||
When running superdive with the environment variable `CI=true` then the UI will be bypassed and will instead analyze your docker image, giving it a pass/fail indication via return code. Currently there are three metrics supported via a `.dive-ci` file that you can put at the root of your repo:
|
||||
```yaml
|
||||
rules:
|
||||
# If the efficiency is measured below X%, mark as failed.
|
||||
# Expressed as a ratio between 0-1.
|
||||
|
|
@ -106,3 +100,7 @@ rules:
|
|||
highestUserWastedPercent: 0.20
|
||||
```
|
||||
You can override the CI config path with the `--ci-config` option.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
version: "3"
|
||||
vars:
|
||||
OWNER: wagoodman
|
||||
PROJECT: dive
|
||||
OWNER: dukaev
|
||||
PROJECT: superdive
|
||||
|
||||
# static file dirs
|
||||
TOOL_DIR: .tool
|
||||
|
|
@ -202,23 +202,9 @@ tasks:
|
|||
ci-test-linux:
|
||||
cmds:
|
||||
- task: ci-test-linux-run
|
||||
- task: ci-test-docker-image
|
||||
- task: ci-test-deb-package-install
|
||||
- task: ci-test-rpm-package-install
|
||||
|
||||
ci-test-docker-image:
|
||||
desc: Test using the docker image
|
||||
cmds:
|
||||
- |
|
||||
docker run \
|
||||
--rm \
|
||||
-t \
|
||||
--env CLICOLOR_FORCE=true \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
'docker.io/wagoodman/dive:latest' \
|
||||
'{{ .TEST_IMAGE }}' \
|
||||
--ci
|
||||
|
||||
ci-test-deb-package-install:
|
||||
desc: Test debian package installation
|
||||
cmds:
|
||||
|
|
@ -237,9 +223,9 @@ tasks:
|
|||
tar -vxzf - docker/docker --strip-component=1 && \
|
||||
mv docker /usr/local/bin/ &&\
|
||||
docker version && \
|
||||
apt install ./snapshot/dive_*_linux_amd64.deb -y && \
|
||||
dive --version && \
|
||||
dive '{{ .TEST_IMAGE }}' --ci \
|
||||
apt install ./snapshot/superdive_*_linux_amd64.deb -y && \
|
||||
superdive --version && \
|
||||
superdive '{{ .TEST_IMAGE }}' --ci \
|
||||
"
|
||||
|
||||
ci-test-rpm-package-install:
|
||||
|
|
@ -258,9 +244,9 @@ tasks:
|
|||
tar -vxzf - docker/docker --strip-component=1 && \
|
||||
mv docker /usr/local/bin/ &&\
|
||||
docker version && \
|
||||
dnf install ./snapshot/dive_*_linux_amd64.rpm -y && \
|
||||
dive --version && \
|
||||
dive '{{ .TEST_IMAGE }}' --ci \
|
||||
dnf install ./snapshot/superdive_*_linux_amd64.rpm -y && \
|
||||
superdive --version && \
|
||||
superdive '{{ .TEST_IMAGE }}' --ci \
|
||||
"
|
||||
|
||||
generate-compressed-test-images:
|
||||
|
|
@ -271,7 +257,7 @@ tasks:
|
|||
for exporter in docker image; do \
|
||||
docker buildx build \
|
||||
-f .data/Dockerfile.minimal \
|
||||
--tag test-dive-${exporter}:${alg} \
|
||||
--tag test-superdive-${exporter}:${alg} \
|
||||
--output type=${exporter},force-compression=true,compression=${alg} . ; \
|
||||
done ; \
|
||||
done && \
|
||||
|
|
@ -298,16 +284,16 @@ tasks:
|
|||
cmds:
|
||||
- |
|
||||
ls -la {{ .SNAPSHOT_DIR }}
|
||||
ls -la {{ .SNAPSHOT_DIR }}/dive_linux_amd64_v1
|
||||
chmod 755 {{ .SNAPSHOT_DIR }}/dive_linux_amd64_v1/dive && \
|
||||
{{ .SNAPSHOT_DIR }}/dive_linux_amd64_v1/dive '{{ .TEST_IMAGE }}' --ci && \
|
||||
{{ .SNAPSHOT_DIR }}/dive_linux_amd64_v1/dive --source docker-archive .data/test-kaniko-image.tar --ci --ci-config .data/.dive-ci
|
||||
ls -la {{ .SNAPSHOT_DIR }}/superdive_linux_amd64_v1
|
||||
chmod 755 {{ .SNAPSHOT_DIR }}/superdive_linux_amd64_v1/superdive && \
|
||||
{{ .SNAPSHOT_DIR }}/superdive_linux_amd64_v1/superdive '{{ .TEST_IMAGE }}' --ci && \
|
||||
{{ .SNAPSHOT_DIR }}/superdive_linux_amd64_v1/superdive --source docker-archive .data/test-kaniko-image.tar --ci --ci-config .data/.dive-ci
|
||||
- |
|
||||
for alg in uncompressed gzip estargz zstd; do \
|
||||
for exporter in docker image; do \
|
||||
{{ .SNAPSHOT_DIR }}/dive_linux_amd64_v1/dive "test-dive-${exporter}:${alg}" --ci ; \
|
||||
{{ .SNAPSHOT_DIR }}/superdive_linux_amd64_v1/superdive "test-superdive-${exporter}:${alg}" --ci ; \
|
||||
done && \
|
||||
{{ .SNAPSHOT_DIR }}/dive_linux_amd64_v1/dive --source docker-archive .data/test-oci-${alg}-image.tar --ci --ci-config .data/.dive-ci; \
|
||||
{{ .SNAPSHOT_DIR }}/superdive_linux_amd64_v1/superdive --source docker-archive .data/test-oci-${alg}-image.tar --ci --ci-config .data/.dive-ci; \
|
||||
done
|
||||
|
||||
ci-test-mac-run:
|
||||
|
|
@ -315,8 +301,8 @@ tasks:
|
|||
deps: [ci-check]
|
||||
cmds:
|
||||
- |
|
||||
chmod 755 {{ .SNAPSHOT_DIR }}/dive_darwin_amd64_v1/dive && \
|
||||
{{ .SNAPSHOT_DIR }}/dive_darwin_amd64_v1/dive --source docker-archive .data/test-docker-image.tar --ci --ci-config .data/.dive-ci
|
||||
chmod 755 {{ .SNAPSHOT_DIR }}/superdive_darwin_amd64_v1/superdive && \
|
||||
{{ .SNAPSHOT_DIR }}/superdive_darwin_amd64_v1/superdive --source docker-archive .data/test-docker-image.tar --ci --ci-config .data/.dive-ci
|
||||
|
||||
|
||||
## Build-related targets #################################
|
||||
|
|
|
|||
38
package.json
Normal file
38
package.json
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"name": "superdive",
|
||||
"version": "0.14.0",
|
||||
"description": "A tool for exploring a Docker image, layer contents, and discovering ways to shrink the size of your Docker/OCI image.",
|
||||
"bin": {
|
||||
"superdive": "bin/superdive.js"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "node scripts/install.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/dukaev/superdive.git"
|
||||
},
|
||||
"keywords": [
|
||||
"docker",
|
||||
"container",
|
||||
"image",
|
||||
"oci",
|
||||
"layer",
|
||||
"dive",
|
||||
"cli"
|
||||
],
|
||||
"author": "Aslan Dukaev",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/dukaev/superdive/issues"
|
||||
},
|
||||
"homepage": "https://github.com/dukaev/superdive#readme",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"files": [
|
||||
"bin",
|
||||
"scripts"
|
||||
]
|
||||
}
|
||||
115
scripts/install.js
Executable file
115
scripts/install.js
Executable file
|
|
@ -0,0 +1,115 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const https = require('https');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
const VERSION = require('../package.json').version;
|
||||
const REPO = 'dukaev/superdive';
|
||||
|
||||
function getPlatform() {
|
||||
const platform = os.platform();
|
||||
switch (platform) {
|
||||
case 'darwin': return 'darwin';
|
||||
case 'linux': return 'linux';
|
||||
case 'win32': return 'windows';
|
||||
default: throw new Error(`Unsupported platform: ${platform}`);
|
||||
}
|
||||
}
|
||||
|
||||
function getArch() {
|
||||
const arch = os.arch();
|
||||
switch (arch) {
|
||||
case 'x64': return 'amd64';
|
||||
case 'arm64': return 'arm64';
|
||||
case 'ia32': return '386';
|
||||
default: throw new Error(`Unsupported architecture: ${arch}`);
|
||||
}
|
||||
}
|
||||
|
||||
function getDownloadUrl() {
|
||||
const platform = getPlatform();
|
||||
const arch = getArch();
|
||||
const ext = platform === 'windows' ? '.zip' : '.tar.gz';
|
||||
return `https://github.com/${REPO}/releases/download/v${VERSION}/superdive_${VERSION}_${platform}_${arch}${ext}`;
|
||||
}
|
||||
|
||||
function download(url, dest) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = fs.createWriteStream(dest);
|
||||
|
||||
const request = (url) => {
|
||||
https.get(url, (response) => {
|
||||
if (response.statusCode === 302 || response.statusCode === 301) {
|
||||
request(response.headers.location);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
reject(new Error(`Failed to download: ${response.statusCode}`));
|
||||
return;
|
||||
}
|
||||
|
||||
response.pipe(file);
|
||||
file.on('finish', () => {
|
||||
file.close();
|
||||
resolve();
|
||||
});
|
||||
}).on('error', (err) => {
|
||||
fs.unlink(dest, () => {});
|
||||
reject(err);
|
||||
});
|
||||
};
|
||||
|
||||
request(url);
|
||||
});
|
||||
}
|
||||
|
||||
async function install() {
|
||||
const platform = getPlatform();
|
||||
const binDir = path.join(__dirname, '..', 'bin');
|
||||
const binaryName = platform === 'windows' ? 'superdive.exe' : 'superdive';
|
||||
const binaryPath = path.join(binDir, binaryName);
|
||||
|
||||
// Skip if binary already exists
|
||||
if (fs.existsSync(binaryPath)) {
|
||||
console.log('superdive binary already exists');
|
||||
return;
|
||||
}
|
||||
|
||||
const url = getDownloadUrl();
|
||||
const ext = platform === 'windows' ? '.zip' : '.tar.gz';
|
||||
const archivePath = path.join(binDir, `superdive${ext}`);
|
||||
|
||||
console.log(`Downloading superdive from ${url}...`);
|
||||
|
||||
try {
|
||||
await download(url, archivePath);
|
||||
|
||||
console.log('Extracting...');
|
||||
|
||||
if (platform === 'windows') {
|
||||
execSync(`powershell -command "Expand-Archive -Path '${archivePath}' -DestinationPath '${binDir}'"`, { stdio: 'inherit' });
|
||||
} else {
|
||||
execSync(`tar -xzf "${archivePath}" -C "${binDir}"`, { stdio: 'inherit' });
|
||||
}
|
||||
|
||||
// Make binary executable
|
||||
if (platform !== 'windows') {
|
||||
fs.chmodSync(binaryPath, 0o755);
|
||||
}
|
||||
|
||||
// Clean up archive
|
||||
fs.unlinkSync(archivePath);
|
||||
|
||||
console.log('superdive installed successfully!');
|
||||
} catch (err) {
|
||||
console.error(`Failed to install superdive: ${err.message}`);
|
||||
console.error('Please install manually from https://github.com/dukaev/superdive/releases');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
install();
|
||||
Loading…
Add table
Add a link
Reference in a new issue