From e2d31f63fda1aa430dd18ef123cc548a4a84f32b Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 12:27:21 -0800 Subject: [PATCH 01/21] feat: add github actions for deployment automation --- .github/workflows/docker-stable.yml | 22 +++++++++++ .github/workflows/pr-preview.yml | 61 +++++++++++++++++++++++++++++ .github/workflows/release.yml | 33 ++++++++++++++++ .github/workflows/version-check.yml | 56 ++++++++++++++++++++++++++ .gitignore | 3 +- Dockerfile | 12 +++++- pyproject.toml | 6 ++- socketsecurity/__init__.py | 2 +- 8 files changed, 190 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/docker-stable.yml create mode 100644 .github/workflows/pr-preview.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/version-check.yml diff --git a/.github/workflows/docker-stable.yml b/.github/workflows/docker-stable.yml new file mode 100644 index 0000000..23cdfd3 --- /dev/null +++ b/.github/workflows/docker-stable.yml @@ -0,0 +1,22 @@ +name: Mark Release as Stable +on: + workflow_dispatch: + inputs: + version: + description: 'Version to mark as stable (e.g., v1.2.3)' + required: true + +jobs: + stable: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build & Push Stable Docker + uses: docker/build-push-action@v5 + with: + push: true + platforms: linux/amd64,linux/arm64 + tags: socketdev/cli:stable + build-args: | + CLI_VERSION=${{ inputs.version }} \ No newline at end of file diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml new file mode 100644 index 0000000..4b16f0b --- /dev/null +++ b/.github/workflows/pr-preview.yml @@ -0,0 +1,61 @@ +name: PR Preview +on: + pull_request: + types: [opened, synchronize] + +jobs: + preview: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Set preview version + run: | + BASE_VERSION=$(grep -o "__version__.*" socketsecurity/__init__.py | awk '{print $3}' | tr -d "'") + echo "VERSION=${BASE_VERSION}.dev${GITHUB_PR_NUMBER}" >> $GITHUB_ENV + + - name: Build package + run: | + pip install build + python -m build + + - name: Publish to Test PyPI + uses: pypa/gh-action-pypi-publish@v1.8.11 + with: + repository-url: https://test.pypi.org/legacy/ + password: ${{ secrets.TEST_PYPI_TOKEN }} + + - name: Comment on PR + uses: actions/github-script@v7 + with: + script: | + const version = process.env.VERSION; + const comment = ` + 🚀 Preview package published! + + Install with: + \`\`\`bash + pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple socketsecurity==${version} + \`\`\` + + Docker image: \`socketdev/cli:pr-${context.issue.number}\` + `; + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.name, + body: comment + }) + + - name: Build & Push Docker Preview + uses: docker/build-push-action@v5 + with: + push: true + tags: socketdev/cli:pr-${{ github.event.pull_request.number }} + build-args: | + CLI_VERSION=${{ env.VERSION }} + PIP_INDEX_URL=https://test.pypi.org/simple \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..0212f55 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,33 @@ +name: Release +on: + push: + tags: + - 'v*' + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Build package + run: | + pip install build + python -m build + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@v1.8.11 + with: + password: ${{ secrets.PYPI_TOKEN }} + + - name: Build & Push Docker + uses: docker/build-push-action@v5 + with: + push: true + platforms: linux/amd64,linux/arm64 + tags: | + socketdev/cli:latest + socketdev/cli:${{ github.ref_name }} \ No newline at end of file diff --git a/.github/workflows/version-check.yml b/.github/workflows/version-check.yml new file mode 100644 index 0000000..1c84c06 --- /dev/null +++ b/.github/workflows/version-check.yml @@ -0,0 +1,56 @@ +name: Version Check +on: + pull_request: + types: [opened, synchronize] + paths: + - 'socketsecurity/**' + - 'setup.py' + - 'pyproject.toml' + +jobs: + check_version: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for all branches + + - name: Check version increment + run: | + # Get version from current PR + PR_VERSION=$(grep -o "__version__.*" socketsecurity/__init__.py | awk '{print $3}' | tr -d "'") + + # Get version from main branch + git checkout origin/main + MAIN_VERSION=$(grep -o "__version__.*" socketsecurity/__init__.py | awk '{print $3}' | tr -d "'") + + # Compare versions using Python + python3 -c " + from packaging import version + pr_ver = version.parse('${PR_VERSION}') + main_ver = version.parse('${MAIN_VERSION}') + if pr_ver <= main_ver: + print(f'❌ Version must be incremented! Main: {main_ver}, PR: {pr_ver}') + exit(1) + print(f'✅ Version properly incremented from {main_ver} to {pr_ver}') + " + + - name: Comment on PR if version check fails + if: failure() + uses: actions/github-script@v7 + with: + script: | + const comment = ` + ❌ **Version Check Failed** + + Please increment the version number in \`socketsecurity/__init__.py\`. + Current version on main: \`${process.env.MAIN_VERSION}\` + Your PR version: \`${process.env.PR_VERSION}\` + `; + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.name, + body: comment + }) \ No newline at end of file diff --git a/.gitignore b/.gitignore index 5738fef..405a91f 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ markdown_security_temp.md *.pyc test.py *.cpython-312.pyc` -file_generator.py \ No newline at end of file +file_generator.py +.env.local \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 569e2fd..1810ff0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,16 @@ FROM python:3-alpine LABEL org.opencontainers.image.authors="socket.dev" ARG CLI_VERSION +ARG PIP_INDEX_URL=https://pypi.org/simple RUN apk update \ && apk add --no-cache git nodejs npm yarn -RUN pip install socketsecurity --upgrade \ + +RUN pip install --index-url ${PIP_INDEX_URL} socketsecurity==$CLI_VERSION \ && socketcli -v \ - && socketcli -v | grep -q $CLI_VERSION \ No newline at end of file + && socketcli -v | grep -q $CLI_VERSION + +# !! Uncomment to test local build - requires running `python -m build` first (and correct version number) +# COPY dist/socketsecurity-1.0.34-py3-none-any.whl /tmp/ +# RUN pip install /tmp/socketsecurity-1.0.34-py3-none-any.whl \ +# && socketcli -v \ +# && socketcli -v | grep -q $CLI_VERSION \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 2c8ddf8..4a730e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,6 @@ dependencies = [ 'prettytable', 'argparse', 'GitPython', - 'packaging' ] readme = "README.md" description = "Socket Security CLI for CI/CD" @@ -32,6 +31,11 @@ classifiers = [ "Programming Language :: Python :: 3.12", ] +[project.optional-dependencies] +dev = [ + "packaging" +] + [project.scripts] socketcli = "socketsecurity.socketcli:cli" diff --git a/socketsecurity/__init__.py b/socketsecurity/__init__.py index 554e76e..9a1ba0c 100644 --- a/socketsecurity/__init__.py +++ b/socketsecurity/__init__.py @@ -1,2 +1,2 @@ __author__ = 'socket.dev' -__version__ = '1.0.32' +__version__ = '1.0.36' From 01370a70f008b871406e98923726e8436cb7079c Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 12:36:55 -0800 Subject: [PATCH 02/21] Packaging moved to main dependencies to support version check code --- pyproject.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4a730e1..abb0472 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,7 @@ dependencies = [ 'prettytable', 'argparse', 'GitPython', + 'packaging', ] readme = "README.md" description = "Socket Security CLI for CI/CD" @@ -31,10 +32,6 @@ classifiers = [ "Programming Language :: Python :: 3.12", ] -[project.optional-dependencies] -dev = [ - "packaging" -] [project.scripts] socketcli = "socketsecurity.socketcli:cli" From c7b491498b191faed9d5d5047592314aac44833c Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 13:01:56 -0800 Subject: [PATCH 03/21] Added dockerhub login steps where needed --- .github/workflows/docker-stable.yml | 6 ++++++ .github/workflows/pr-preview.yml | 6 ++++++ .github/workflows/release.yml | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/.github/workflows/docker-stable.yml b/.github/workflows/docker-stable.yml index 23cdfd3..394dde1 100644 --- a/.github/workflows/docker-stable.yml +++ b/.github/workflows/docker-stable.yml @@ -12,6 +12,12 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build & Push Stable Docker uses: docker/build-push-action@v5 with: diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 4b16f0b..3d6a5db 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -51,6 +51,12 @@ jobs: body: comment }) + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build & Push Docker Preview uses: docker/build-push-action@v5 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0212f55..dab4191 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,6 +23,12 @@ jobs: with: password: ${{ secrets.PYPI_TOKEN }} + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build & Push Docker uses: docker/build-push-action@v5 with: From 75b80ccfc7d9234234662633c755c7dbc14a641c Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 13:21:58 -0800 Subject: [PATCH 04/21] added the commit sha to the generated preview version to ensure uniqueness. --- .github/workflows/pr-preview.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 3d6a5db..0e399b1 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -15,14 +15,28 @@ jobs: - name: Set preview version run: | BASE_VERSION=$(grep -o "__version__.*" socketsecurity/__init__.py | awk '{print $3}' | tr -d "'") - echo "VERSION=${BASE_VERSION}.dev${GITHUB_PR_NUMBER}" >> $GITHUB_ENV + SHORT_SHA=$(git rev-parse --short HEAD) + echo "VERSION=${BASE_VERSION}.dev${GITHUB_PR_NUMBER}+${SHORT_SHA}" >> $GITHUB_ENV + + - name: Check if version exists on Test PyPI + id: version_check + run: | + if pip index versions --index-url https://test.pypi.org/simple/ socketsecurity | grep -q "${VERSION}"; then + echo "Version ${VERSION} already exists on Test PyPI" + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "Version ${VERSION} not found on Test PyPI" + echo "exists=false" >> $GITHUB_OUTPUT + fi - name: Build package + if: steps.version_check.outputs.exists != 'true' run: | pip install build python -m build - name: Publish to Test PyPI + if: steps.version_check.outputs.exists != 'true' uses: pypa/gh-action-pypi-publish@v1.8.11 with: repository-url: https://test.pypi.org/legacy/ From e9b991996148996c51d2a2d227a04fcb8233e83f Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 13:29:16 -0800 Subject: [PATCH 05/21] Actually setting preview version in init --- .github/workflows/pr-preview.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 0e399b1..61315f1 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -16,7 +16,11 @@ jobs: run: | BASE_VERSION=$(grep -o "__version__.*" socketsecurity/__init__.py | awk '{print $3}' | tr -d "'") SHORT_SHA=$(git rev-parse --short HEAD) - echo "VERSION=${BASE_VERSION}.dev${GITHUB_PR_NUMBER}+${SHORT_SHA}" >> $GITHUB_ENV + PREVIEW_VERSION="${BASE_VERSION}.dev${GITHUB_PR_NUMBER}+${SHORT_SHA}" + echo "VERSION=${PREVIEW_VERSION}" >> $GITHUB_ENV + + # Temporarily update the version in __init__.py + sed -i "s/__version__ = \"${BASE_VERSION}\"/__version__ = \"${PREVIEW_VERSION}\"/" socketsecurity/__init__.py - name: Check if version exists on Test PyPI id: version_check @@ -35,6 +39,12 @@ jobs: pip install build python -m build + - name: Restore original version + if: always() # Run even if previous steps fail + run: | + BASE_VERSION=$(echo $VERSION | cut -d'.' -f1-3) + sed -i "s/__version__ = \"${VERSION}\"/__version__ = \"${BASE_VERSION}\"/" socketsecurity/__init__.py + - name: Publish to Test PyPI if: steps.version_check.outputs.exists != 'true' uses: pypa/gh-action-pypi-publish@v1.8.11 From ac18fa253e2fb4fcce7442a117de5a7141917df7 Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 13:35:22 -0800 Subject: [PATCH 06/21] Still working on the version handling --- .github/workflows/pr-preview.yml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 61315f1..ab5be53 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -19,8 +19,14 @@ jobs: PREVIEW_VERSION="${BASE_VERSION}.dev${GITHUB_PR_NUMBER}+${SHORT_SHA}" echo "VERSION=${PREVIEW_VERSION}" >> $GITHUB_ENV - # Temporarily update the version in __init__.py - sed -i "s/__version__ = \"${BASE_VERSION}\"/__version__ = \"${PREVIEW_VERSION}\"/" socketsecurity/__init__.py + # Update version in __init__.py + echo "__version__ = \"${PREVIEW_VERSION}\"" > socketsecurity/__init__.py.tmp + cat socketsecurity/__init__.py | grep -v "__version__" >> socketsecurity/__init__.py.tmp + mv socketsecurity/__init__.py.tmp socketsecurity/__init__.py + + # Verify the change + echo "Updated version in __init__.py:" + cat socketsecurity/__init__.py | grep "__version__" - name: Check if version exists on Test PyPI id: version_check @@ -40,10 +46,12 @@ jobs: python -m build - name: Restore original version - if: always() # Run even if previous steps fail + if: always() run: | BASE_VERSION=$(echo $VERSION | cut -d'.' -f1-3) - sed -i "s/__version__ = \"${VERSION}\"/__version__ = \"${BASE_VERSION}\"/" socketsecurity/__init__.py + echo "__version__ = \"${BASE_VERSION}\"" > socketsecurity/__init__.py.tmp + cat socketsecurity/__init__.py | grep -v "__version__" >> socketsecurity/__init__.py.tmp + mv socketsecurity/__init__.py.tmp socketsecurity/__init__.py - name: Publish to Test PyPI if: steps.version_check.outputs.exists != 'true' @@ -51,6 +59,7 @@ jobs: with: repository-url: https://test.pypi.org/legacy/ password: ${{ secrets.TEST_PYPI_TOKEN }} + verbose: true - name: Comment on PR uses: actions/github-script@v7 From 55e0b41ccc533dae35f1e41f55edee05e6e05147 Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 13:39:04 -0800 Subject: [PATCH 07/21] Local versions are not allowed in pypi as per PEP440 --- .github/workflows/pr-preview.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index ab5be53..8c5d17e 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -16,7 +16,7 @@ jobs: run: | BASE_VERSION=$(grep -o "__version__.*" socketsecurity/__init__.py | awk '{print $3}' | tr -d "'") SHORT_SHA=$(git rev-parse --short HEAD) - PREVIEW_VERSION="${BASE_VERSION}.dev${GITHUB_PR_NUMBER}+${SHORT_SHA}" + PREVIEW_VERSION="${BASE_VERSION}.dev${GITHUB_PR_NUMBER}.post${SHORT_SHA}" echo "VERSION=${PREVIEW_VERSION}" >> $GITHUB_ENV # Update version in __init__.py From c738a85615dece5d209814acb9518b3208e233ac Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 13:54:13 -0800 Subject: [PATCH 08/21] More versioning fun --- .github/workflows/pr-preview.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 8c5d17e..6a4d900 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -15,8 +15,8 @@ jobs: - name: Set preview version run: | BASE_VERSION=$(grep -o "__version__.*" socketsecurity/__init__.py | awk '{print $3}' | tr -d "'") - SHORT_SHA=$(git rev-parse --short HEAD) - PREVIEW_VERSION="${BASE_VERSION}.dev${GITHUB_PR_NUMBER}.post${SHORT_SHA}" + SHORT_SHA=$(echo "${{ github.event.pull_request.head.sha }}" | cut -c1-7) + PREVIEW_VERSION="${BASE_VERSION}.dev${{ github.event.pull_request.number }}.post${SHORT_SHA}" echo "VERSION=${PREVIEW_VERSION}" >> $GITHUB_ENV # Update version in __init__.py From abfc2107a10eeda52873fc028d71589f8deaf7e9 Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 14:21:49 -0800 Subject: [PATCH 09/21] PEP 440 specifier shenanigans --- .github/workflows/pr-preview.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 6a4d900..4c826de 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -15,8 +15,7 @@ jobs: - name: Set preview version run: | BASE_VERSION=$(grep -o "__version__.*" socketsecurity/__init__.py | awk '{print $3}' | tr -d "'") - SHORT_SHA=$(echo "${{ github.event.pull_request.head.sha }}" | cut -c1-7) - PREVIEW_VERSION="${BASE_VERSION}.dev${{ github.event.pull_request.number }}.post${SHORT_SHA}" + PREVIEW_VERSION="${BASE_VERSION}.dev${{ github.event.pull_request.number }}${{ github.event.pull_request.commits }}" echo "VERSION=${PREVIEW_VERSION}" >> $GITHUB_ENV # Update version in __init__.py From 34ebc53452291eee954f0ca779c2dcccb89cf39b Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 14:33:13 -0800 Subject: [PATCH 10/21] fixing pr commenting step --- .github/workflows/pr-preview.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 4c826de..65c0882 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -62,9 +62,12 @@ jobs: - name: Comment on PR uses: actions/github-script@v7 + env: + VERSION: ${{ env.VERSION }} with: script: | const version = process.env.VERSION; + const prNumber = context.payload.pull_request.number; const comment = ` 🚀 Preview package published! @@ -73,15 +76,16 @@ jobs: pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple socketsecurity==${version} \`\`\` - Docker image: \`socketdev/cli:pr-${context.issue.number}\` + Docker image: \`socketdev/cli:pr-${prNumber}\` `; github.rest.issues.createComment({ - issue_number: context.issue.number, + issue_number: prNumber, owner: context.repo.owner, repo: context.repo.name, body: comment - }) + }); + - name: Login to Docker Hub uses: docker/login-action@v3 @@ -91,6 +95,8 @@ jobs: - name: Build & Push Docker Preview uses: docker/build-push-action@v5 + env: + VERSION: ${{ env.VERSION }} with: push: true tags: socketdev/cli:pr-${{ github.event.pull_request.number }} From dc440a107d4da5806f4e275ef7bc86d4b510c877 Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 14:42:16 -0800 Subject: [PATCH 11/21] Forcing the repo name to populate in comment pr step --- .github/workflows/pr-preview.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 65c0882..bede1cf 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -68,6 +68,14 @@ jobs: script: | const version = process.env.VERSION; const prNumber = context.payload.pull_request.number; + const owner = context.repo.owner; + const repo = context.repo.repo; + + // Log the values for debugging + console.log("Owner:", context.repo.owner); + console.log("Repo:", context.repo.repo); + console.log("Context Repo:", JSON.stringify(context.repo, null, 2)); + const comment = ` 🚀 Preview package published! @@ -80,13 +88,14 @@ jobs: `; github.rest.issues.createComment({ + owner: owner, + repo: repo, issue_number: prNumber, - owner: context.repo.owner, - repo: context.repo.name, body: comment }); + - name: Login to Docker Hub uses: docker/login-action@v3 with: From 12976ab254974e4709fc5b4136bfee196834c118 Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 15:08:13 -0800 Subject: [PATCH 12/21] better version checking --- .github/workflows/pr-preview.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index bede1cf..cdd1255 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -30,8 +30,9 @@ jobs: - name: Check if version exists on Test PyPI id: version_check run: | - if pip index versions --index-url https://test.pypi.org/simple/ socketsecurity | grep -q "${VERSION}"; then - echo "Version ${VERSION} already exists on Test PyPI" + # Try both exact version check and pip install dry-run + if pip download --no-deps --dry-run --index-url https://test.pypi.org/simple/ "socketsecurity==${VERSION}" 2>/dev/null; then + echo "Version ${VERSION} already exists on Test PyPI (found via pip download)" echo "exists=true" >> $GITHUB_OUTPUT else echo "Version ${VERSION} not found on Test PyPI" From 175e962840e42ddbc6aad04439f248d1a8d110fd Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 15:21:35 -0800 Subject: [PATCH 13/21] added a step to wait for new package avail before docker build --- .github/workflows/pr-preview.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index cdd1255..6bea8b3 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -62,6 +62,7 @@ jobs: verbose: true - name: Comment on PR + if: steps.version_check.outputs.exists != 'true' uses: actions/github-script@v7 env: VERSION: ${{ env.VERSION }} @@ -95,7 +96,21 @@ jobs: body: comment }); - + - name: Verify package is available + if: steps.version_check.outputs.exists != 'true' + id: verify_package + run: | + # Wait for package to be available (try up to 5 times with 30s delay) + for i in {1..5}; do + if pip download --no-deps --dry-run --index-url https://test.pypi.org/simple/ "socketsecurity==${VERSION}" 2>/dev/null; then + echo "Package ${VERSION} is now available on Test PyPI" + exit 0 + fi + echo "Attempt $i: Package not yet available, waiting 30s..." + sleep 30 + done + echo "Package ${VERSION} not available after 5 attempts" + exit 1 - name: Login to Docker Hub uses: docker/login-action@v3 From d14dcc772608db8d0ca66299eaef207a47e550c3 Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 15:30:38 -0800 Subject: [PATCH 14/21] querying pypi metadata directly --- .github/workflows/pr-preview.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 6bea8b3..b1fb537 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -30,9 +30,8 @@ jobs: - name: Check if version exists on Test PyPI id: version_check run: | - # Try both exact version check and pip install dry-run - if pip download --no-deps --dry-run --index-url https://test.pypi.org/simple/ "socketsecurity==${VERSION}" 2>/dev/null; then - echo "Version ${VERSION} already exists on Test PyPI (found via pip download)" + if curl -s https://test.pypi.org/pypi/socketsecurity/$VERSION/json | grep -q '"version": "'$VERSION'"'; then + echo "Version ${VERSION} already exists on Test PyPI" echo "exists=true" >> $GITHUB_OUTPUT else echo "Version ${VERSION} not found on Test PyPI" @@ -100,14 +99,14 @@ jobs: if: steps.version_check.outputs.exists != 'true' id: verify_package run: | - # Wait for package to be available (try up to 5 times with 30s delay) + # Wait for package to be available (try up to 5 times with 10s delay) for i in {1..5}; do - if pip download --no-deps --dry-run --index-url https://test.pypi.org/simple/ "socketsecurity==${VERSION}" 2>/dev/null; then + if curl -s https://test.pypi.org/pypi/socketsecurity/$VERSION/json | grep -q '"version": "'$VERSION'"'; then echo "Package ${VERSION} is now available on Test PyPI" exit 0 fi - echo "Attempt $i: Package not yet available, waiting 30s..." - sleep 30 + echo "Attempt $i: Package not yet available, waiting 10s..." + sleep 10 done echo "Package ${VERSION} not available after 5 attempts" exit 1 From 6495d9781d68049f3610e08c314e2402f38b314e Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 15:33:21 -0800 Subject: [PATCH 15/21] waiting longer for the package to appear --- .github/workflows/pr-preview.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index b1fb537..db9ff60 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -99,14 +99,14 @@ jobs: if: steps.version_check.outputs.exists != 'true' id: verify_package run: | - # Wait for package to be available (try up to 5 times with 10s delay) + # Wait for package to be available (try up to 5 times with 60s delay) for i in {1..5}; do if curl -s https://test.pypi.org/pypi/socketsecurity/$VERSION/json | grep -q '"version": "'$VERSION'"'; then echo "Package ${VERSION} is now available on Test PyPI" exit 0 fi - echo "Attempt $i: Package not yet available, waiting 10s..." - sleep 10 + echo "Attempt $i: Package not yet available, waiting 60s..." + sleep 60 done echo "Package ${VERSION} not available after 5 attempts" exit 1 From fbbdfc15a97c8e1c19ab008a5c3896c7b3ed9441 Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 15:38:15 -0800 Subject: [PATCH 16/21] forgot to add the env var to the steps --- .github/workflows/pr-preview.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index db9ff60..d9455b8 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -29,6 +29,8 @@ jobs: - name: Check if version exists on Test PyPI id: version_check + env: + VERSION: ${{ env.VERSION }} run: | if curl -s https://test.pypi.org/pypi/socketsecurity/$VERSION/json | grep -q '"version": "'$VERSION'"'; then echo "Version ${VERSION} already exists on Test PyPI" @@ -98,6 +100,8 @@ jobs: - name: Verify package is available if: steps.version_check.outputs.exists != 'true' id: verify_package + env: + VERSION: ${{ env.VERSION }} run: | # Wait for package to be available (try up to 5 times with 60s delay) for i in {1..5}; do From b9b0d25250da56475219fa9d4fe13b149bacdc90 Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 17:23:35 -0800 Subject: [PATCH 17/21] I hate pypi. --- .github/workflows/pr-preview.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index d9455b8..aa71b3d 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -32,7 +32,7 @@ jobs: env: VERSION: ${{ env.VERSION }} run: | - if curl -s https://test.pypi.org/pypi/socketsecurity/$VERSION/json | grep -q '"version": "'$VERSION'"'; then + if curl -s -f https://test.pypi.org/pypi/socketsecurity/$VERSION/json > /dev/null; then echo "Version ${VERSION} already exists on Test PyPI" echo "exists=true" >> $GITHUB_OUTPUT else @@ -103,16 +103,16 @@ jobs: env: VERSION: ${{ env.VERSION }} run: | - # Wait for package to be available (try up to 5 times with 60s delay) - for i in {1..5}; do - if curl -s https://test.pypi.org/pypi/socketsecurity/$VERSION/json | grep -q '"version": "'$VERSION'"'; then + # Wait for package to be available (try up to 30 times with 20s delay - total 10 minutes) + for i in {1..30}; do + if curl -s -f https://test.pypi.org/pypi/socketsecurity/$VERSION/json > /dev/null; then echo "Package ${VERSION} is now available on Test PyPI" exit 0 fi - echo "Attempt $i: Package not yet available, waiting 60s..." - sleep 60 + echo "Attempt $i: Package not yet available, waiting 20s... (${i}/30)" + sleep 20 done - echo "Package ${VERSION} not available after 5 attempts" + echo "Package ${VERSION} not available after 10 minutes" exit 1 - name: Login to Docker Hub From 923f9cc32b2f0436c39aa81e478d33a4acca46ff Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 17:36:58 -0800 Subject: [PATCH 18/21] resolving weird pip issues, remove argparse as its built-in --- .github/workflows/pr-preview.yml | 3 ++- Dockerfile | 12 ++++-------- pyproject.toml | 1 - 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index aa71b3d..2596963 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -130,4 +130,5 @@ jobs: tags: socketdev/cli:pr-${{ github.event.pull_request.number }} build-args: | CLI_VERSION=${{ env.VERSION }} - PIP_INDEX_URL=https://test.pypi.org/simple \ No newline at end of file + PIP_INDEX_URL=https://test.pypi.org/simple + PIP_EXTRA_INDEX_URL=https://pypi.org/simple \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 1810ff0..949ec58 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,15 +2,11 @@ FROM python:3-alpine LABEL org.opencontainers.image.authors="socket.dev" ARG CLI_VERSION ARG PIP_INDEX_URL=https://pypi.org/simple +ARG PIP_EXTRA_INDEX_URL=https://pypi.org/simple + RUN apk update \ && apk add --no-cache git nodejs npm yarn -RUN pip install --index-url ${PIP_INDEX_URL} socketsecurity==$CLI_VERSION \ +RUN pip install --index-url ${PIP_INDEX_URL} --extra-index-url ${PIP_EXTRA_INDEX_URL} socketsecurity==$CLI_VERSION \ && socketcli -v \ - && socketcli -v | grep -q $CLI_VERSION - -# !! Uncomment to test local build - requires running `python -m build` first (and correct version number) -# COPY dist/socketsecurity-1.0.34-py3-none-any.whl /tmp/ -# RUN pip install /tmp/socketsecurity-1.0.34-py3-none-any.whl \ -# && socketcli -v \ -# && socketcli -v | grep -q $CLI_VERSION \ No newline at end of file + && socketcli -v | grep -q $CLI_VERSION \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index abb0472..7ff90d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,6 @@ dependencies = [ 'requests', 'mdutils', 'prettytable', - 'argparse', 'GitPython', 'packaging', ] From 7a389afdfffe16ab775aaeae3668a1308f1edbdb Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 17:48:24 -0800 Subject: [PATCH 19/21] trying a more deterministic approach to package version verification --- .github/workflows/pr-preview.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 2596963..9c9eb1f 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -103,25 +103,28 @@ jobs: env: VERSION: ${{ env.VERSION }} run: | - # Wait for package to be available (try up to 30 times with 20s delay - total 10 minutes) for i in {1..30}; do - if curl -s -f https://test.pypi.org/pypi/socketsecurity/$VERSION/json > /dev/null; then - echo "Package ${VERSION} is now available on Test PyPI" + if pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple socketsecurity==${VERSION}; then + echo "Package ${VERSION} is now available and installable on Test PyPI" + pip uninstall -y socketsecurity + echo "success=true" >> $GITHUB_OUTPUT exit 0 fi - echo "Attempt $i: Package not yet available, waiting 20s... (${i}/30)" + echo "Attempt $i: Package not yet installable, waiting 20s... (${i}/30)" sleep 20 done - echo "Package ${VERSION} not available after 10 minutes" + echo "success=false" >> $GITHUB_OUTPUT exit 1 - name: Login to Docker Hub + if: steps.verify_package.outputs.success == 'true' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build & Push Docker Preview + if: steps.verify_package.outputs.success == 'true' uses: docker/build-push-action@v5 env: VERSION: ${{ env.VERSION }} From d925f1fef80ad88415d9a335929bbc230ec17cd1 Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Wed, 6 Nov 2024 22:57:34 -0800 Subject: [PATCH 20/21] cleaned up comment behavior, updated release and stable --- .github/workflows/docker-stable.yml | 11 ++++- .github/workflows/pr-preview.yml | 37 ++++++++++++----- .github/workflows/release.yml | 45 ++++++++++++++++++++- .github/workflows/version-check.yml | 62 ++++++++++++++++++++++------- 4 files changed, 129 insertions(+), 26 deletions(-) diff --git a/.github/workflows/docker-stable.yml b/.github/workflows/docker-stable.yml index 394dde1..0f113b0 100644 --- a/.github/workflows/docker-stable.yml +++ b/.github/workflows/docker-stable.yml @@ -3,7 +3,7 @@ on: workflow_dispatch: inputs: version: - description: 'Version to mark as stable (e.g., v1.2.3)' + description: 'Version to mark as stable (e.g., 1.2.3)' required: true jobs: @@ -12,6 +12,15 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Check if version exists in PyPI + id: version_check + run: | + if ! curl -s -f https://pypi.org/pypi/socketsecurity/${{ inputs.version }}/json > /dev/null; then + echo "Error: Version ${{ inputs.version }} not found on PyPI" + exit 1 + fi + echo "Version ${{ inputs.version }} found on PyPI - proceeding with release" + - name: Login to Docker Hub uses: docker/login-action@v3 with: diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml index 9c9eb1f..8fdd667 100644 --- a/.github/workflows/pr-preview.yml +++ b/.github/workflows/pr-preview.yml @@ -73,11 +73,17 @@ jobs: const prNumber = context.payload.pull_request.number; const owner = context.repo.owner; const repo = context.repo.repo; + // Find existing bot comments + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + }); - // Log the values for debugging - console.log("Owner:", context.repo.owner); - console.log("Repo:", context.repo.repo); - console.log("Context Repo:", JSON.stringify(context.repo, null, 2)); + const botComment = comments.data.find(comment => + comment.user.type === 'Bot' && + comment.body.includes('🚀 Preview package published!') + ); const comment = ` 🚀 Preview package published! @@ -90,12 +96,23 @@ jobs: Docker image: \`socketdev/cli:pr-${prNumber}\` `; - github.rest.issues.createComment({ - owner: owner, - repo: repo, - issue_number: prNumber, - body: comment - }); + if (botComment) { + // Update existing comment + await github.rest.issues.updateComment({ + owner: owner, + repo: repo, + comment_id: botComment.id, + body: comment + }); + } else { + // Create new comment + await github.rest.issues.createComment({ + owner: owner, + repo: repo, + issue_number: prNumber, + body: comment + }); + } - name: Verify package is available if: steps.version_check.outputs.exists != 'true' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dab4191..bdcfed8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,28 @@ jobs: with: python-version: '3.x' + - name: Get Version + id: version + run: | + RAW_VERSION=$(python -c "from socketsecurity import __version__; print(__version__)") + echo "VERSION=$RAW_VERSION" >> $GITHUB_ENV + if [ "v$RAW_VERSION" != "${{ github.ref_name }}" ]; then + echo "Error: Git tag (${{ github.ref_name }}) does not match package version (v$RAW_VERSION)" + exit 1 + fi + + - name: Check if version exists on PyPI + id: version_check + env: + VERSION: ${{ env.VERSION }} + run: | + if curl -s -f https://pypi.org/pypi/socketsecurity/$VERSION/json > /dev/null; then + echo "Error: Version ${VERSION} already exists on PyPI" + exit 1 + else + echo "Version ${VERSION} not found on PyPI - proceeding with release" + fi + - name: Build package run: | pip install build @@ -29,11 +51,32 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Verify package is available + id: verify_package + env: + VERSION: ${{ env.VERSION }} + run: | + for i in {1..30}; do + if pip install socketsecurity==${VERSION}; then + echo "Package ${VERSION} is now available and installable on PyPI" + pip uninstall -y socketsecurity + echo "success=true" >> $GITHUB_OUTPUT + exit 0 + fi + echo "Attempt $i: Package not yet installable, waiting 20s... (${i}/30)" + sleep 20 + done + echo "success=false" >> $GITHUB_OUTPUT + exit 1 + - name: Build & Push Docker + if: steps.verify_package.outputs.success == 'true' uses: docker/build-push-action@v5 + env: + VERSION: ${{ env.VERSION }} with: push: true platforms: linux/amd64,linux/arm64 tags: | socketdev/cli:latest - socketdev/cli:${{ github.ref_name }} \ No newline at end of file + socketdev/cli:${{ env.VERSION }} \ No newline at end of file diff --git a/.github/workflows/version-check.yml b/.github/workflows/version-check.yml index 1c84c06..96cdc09 100644 --- a/.github/workflows/version-check.yml +++ b/.github/workflows/version-check.yml @@ -16,13 +16,16 @@ jobs: fetch-depth: 0 # Fetch all history for all branches - name: Check version increment + id: version_check run: | # Get version from current PR PR_VERSION=$(grep -o "__version__.*" socketsecurity/__init__.py | awk '{print $3}' | tr -d "'") + echo "PR_VERSION=$PR_VERSION" >> $GITHUB_ENV # Get version from main branch git checkout origin/main MAIN_VERSION=$(grep -o "__version__.*" socketsecurity/__init__.py | awk '{print $3}' | tr -d "'") + echo "MAIN_VERSION=$MAIN_VERSION" >> $GITHUB_ENV # Compare versions using Python python3 -c " @@ -35,22 +38,53 @@ jobs: print(f'✅ Version properly incremented from {main_ver} to {pr_ver}') " - - name: Comment on PR if version check fails - if: failure() + - name: Manage PR Comment uses: actions/github-script@v7 + if: always() + env: + MAIN_VERSION: ${{ env.MAIN_VERSION }} + PR_VERSION: ${{ env.PR_VERSION }} + CHECK_RESULT: ${{ steps.version_check.outcome }} with: script: | - const comment = ` - ❌ **Version Check Failed** + const success = process.env.CHECK_RESULT === 'success'; + const prNumber = context.payload.pull_request.number; + const owner = context.repo.owner; + const repo = context.repo.repo; + const comments = await github.rest.issues.listComments({ + owner: owner, + repo: repo, + issue_number: prNumber, + }); - Please increment the version number in \`socketsecurity/__init__.py\`. - Current version on main: \`${process.env.MAIN_VERSION}\` - Your PR version: \`${process.env.PR_VERSION}\` - `; + const versionComment = comments.data.find(comment => + comment.user.type === 'Bot' && + comment.body.includes('Version Check') + ); - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.name, - body: comment - }) \ No newline at end of file + if (versionComment) { + if (success) { + // Delete the warning comment if check passes + await github.rest.issues.deleteComment({ + owner: owner, + repo: repo, + comment_id: versionComment.id + }); + } else { + // Update existing warning + await github.rest.issues.updateComment({ + owner: owner, + repo: repo, + comment_id: versionComment.id, + body: `❌ **Version Check Failed**\n\nPlease increment...` + }); + } + } else if (!success) { + // Create new warning comment only if check fails + await github.rest.issues.createComment({ + owner: owner, + repo: repo, + issue_number: prNumber, + body: `❌ **Version Check Failed**\n\nPlease increment...` + }); + } \ No newline at end of file From fc23da7adf2b75f9ad6e649667bcc9a92c53ced3 Mon Sep 17 00:00:00 2001 From: Eric Hibbs Date: Thu, 7 Nov 2024 12:26:36 -0800 Subject: [PATCH 21/21] made release workflow idempotent --- .github/workflows/release.yml | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bdcfed8..1004ce6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,18 +29,33 @@ jobs: VERSION: ${{ env.VERSION }} run: | if curl -s -f https://pypi.org/pypi/socketsecurity/$VERSION/json > /dev/null; then - echo "Error: Version ${VERSION} already exists on PyPI" - exit 1 + echo "Version ${VERSION} already exists on PyPI" + echo "pypi_exists=true" >> $GITHUB_OUTPUT + else + echo "Version ${VERSION} not found on PyPI - proceeding with PyPI deployment" + echo "pypi_exists=false" >> $GITHUB_OUTPUT + fi + + - name: Check Docker image existence + id: docker_check + env: + VERSION: ${{ env.VERSION }} + run: | + if curl -s -f "https://hub.docker.com/v2/repositories/socketdev/cli/tags/${{ env.VERSION }}" > /dev/null; then + echo "Docker image socketdev/cli:${VERSION} already exists" + echo "docker_exists=true" >> $GITHUB_OUTPUT else - echo "Version ${VERSION} not found on PyPI - proceeding with release" + echo "docker_exists=false" >> $GITHUB_OUTPUT fi - name: Build package + if: steps.version_check.outputs.pypi_exists != 'true' run: | pip install build python -m build - name: Publish to PyPI + if: steps.version_check.outputs.pypi_exists != 'true' uses: pypa/gh-action-pypi-publish@v1.8.11 with: password: ${{ secrets.PYPI_TOKEN }} @@ -51,7 +66,7 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Verify package is available + - name: Verify package is installable id: verify_package env: VERSION: ${{ env.VERSION }} @@ -70,7 +85,9 @@ jobs: exit 1 - name: Build & Push Docker - if: steps.verify_package.outputs.success == 'true' + if: | + steps.verify_package.outputs.success == 'true' && + steps.docker_check.outputs.docker_exists != 'true' uses: docker/build-push-action@v5 env: VERSION: ${{ env.VERSION }}