From 2cf09c27828ccde65853426bf6f3bade5efa9fd0 Mon Sep 17 00:00:00 2001 From: Randy Westergren Date: Sun, 13 Nov 2022 10:33:46 -0500 Subject: [PATCH] fix: Add legacy `pipenv` backward compatability --- .github/workflows/integrate.yml | 9 ++-- .github/workflows/validate.yml | 9 ++-- README.md | 3 +- lib/pipenv.js | 94 ++++++++++++++++++++++++++------- package.json | 1 + 5 files changed, 88 insertions(+), 28 deletions(-) diff --git a/.github/workflows/integrate.yml b/.github/workflows/integrate.yml index 1f979b0a..b0ca0207 100644 --- a/.github/workflows/integrate.yml +++ b/.github/workflows/integrate.yml @@ -16,6 +16,7 @@ jobs: strategy: matrix: sls-version: [2, 3] + pipenv-version: ['2022.8.5', '2022.8.13'] steps: - name: Checkout repository uses: actions/checkout@v2 @@ -48,7 +49,7 @@ jobs: run: python -m pip install --force setuptools wheel - name: Install pipenv / poetry - run: python -m pip install pipenv poetry + run: python -m pip install pipenv==${{ matrix.pipenv-version }} poetry - name: Install serverless run: npm install -g serverless@${{ matrix.sls-version }} @@ -67,6 +68,7 @@ jobs: strategy: matrix: sls-version: [2, 3] + pipenv-version: ['2022.8.5', '2022.8.13'] steps: - name: Checkout repository uses: actions/checkout@v2 @@ -99,7 +101,7 @@ jobs: run: python -m pip install --force setuptools wheel - name: Install pipenv / poetry - run: python -m pip install pipenv poetry + run: python -m pip install pipenv==${{ matrix.pipenv-version }} poetry - name: Install serverless run: npm install -g serverless@${{ matrix.sls-version }} @@ -147,7 +149,7 @@ jobs: run: python -m pip install --force setuptools wheel - name: Install pipenv / poetry - run: python -m pip install pipenv poetry + run: python -m pip install pipenv==${{ matrix.pipenv-version }} poetry - name: Install serverless run: npm install -g serverless@${{ matrix.sls-version }} @@ -166,6 +168,7 @@ jobs: strategy: matrix: sls-version: [2, 3] + pipenv-version: ['2022.8.5', '2022.8.13'] needs: [windowsNode14, linuxNode14, linuxNode12] steps: - name: Checkout repository diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 31052279..e77f6cce 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -16,6 +16,7 @@ jobs: strategy: matrix: sls-version: [2, 3] + pipenv-version: ['2022.8.5', '2022.8.13'] steps: - name: Checkout repository uses: actions/checkout@v2 @@ -61,7 +62,7 @@ jobs: run: python -m pip install --force setuptools wheel - name: Install pipenv / poetry - run: python -m pip install pipenv poetry + run: python -m pip install pipenv==${{ matrix.pipenv-version }} poetry - name: Install serverless run: npm install -g serverless@${{ matrix.sls-version }} @@ -94,6 +95,7 @@ jobs: strategy: matrix: sls-version: [2, 3] + pipenv-version: ['2022.8.5', '2022.8.13'] steps: - name: Checkout repository uses: actions/checkout@v2 @@ -128,7 +130,7 @@ jobs: run: python -m pip install --force setuptools wheel - name: Install pipenv / poetry - run: python -m pip install pipenv poetry + run: python -m pip install pipenv==${{ matrix.pipenv-version }} poetry - name: Install serverless run: npm install -g serverless@${{ matrix.sls-version }} @@ -147,6 +149,7 @@ jobs: strategy: matrix: sls-version: [2, 3] + pipenv-version: ['2022.8.5', '2022.8.13'] steps: - name: Checkout repository uses: actions/checkout@v2 @@ -181,7 +184,7 @@ jobs: run: python -m pip install --force setuptools wheel - name: Install pipenv / poetry - run: python -m pip install pipenv poetry + run: python -m pip install pipenv==${{ matrix.pipenv-version }} poetry - name: Install serverless run: npm install -g serverless@${{ matrix.sls-version }} diff --git a/README.md b/README.md index e0f27ac3..2bb4e4a1 100644 --- a/README.md +++ b/README.md @@ -111,8 +111,7 @@ custom: Requires `pipenv` in version `2022-04-08` or higher. -If you include a `Pipfile` and have `pipenv` installed instead of a `requirements.txt` this will use -`pipenv lock -r` to generate them. It is fully compatible with all options such as `zip` and +If you include a `Pipfile` and have `pipenv` installed, this will use `pipenv` to generate requirements instead of a `requirements.txt`. It is fully compatible with all options such as `zip` and `dockerizePip`. If you don't want this plugin to generate it for you, set the following option: ```yaml diff --git a/lib/pipenv.js b/lib/pipenv.js index 11331ee3..c59fe26a 100644 --- a/lib/pipenv.js +++ b/lib/pipenv.js @@ -2,6 +2,43 @@ const fse = require('fs-extra'); const path = require('path'); const spawn = require('child-process-ext/spawn'); const { EOL } = require('os'); +const semver = require('semver'); + +const LEGACY_PIPENV_VERSION = '2022.8.5'; + +async function getPipenvVersion() { + try { + const res = await spawn('pipenv', ['--version'], { + cwd: this.servicePath, + }); + + const stdoutBuffer = + (res.stdoutBuffer && res.stdoutBuffer.toString().trim()) || ''; + + const version = stdoutBuffer.split(' ')[2]; + + if (semver.valid(version)) { + return version; + } else { + throw new this.serverless.classes.Error( + `Unable to parse pipenv version!`, + 'PYTHON_REQUIREMENTS_PIPENV_VERSION_ERROR' + ); + } + } catch (e) { + const stderrBufferContent = + (e.stderrBuffer && e.stderrBuffer.toString()) || ''; + + if (stderrBufferContent.includes('command not found')) { + throw new this.serverless.classes.Error( + `pipenv not found! Install it according to the pipenv docs.`, + 'PYTHON_REQUIREMENTS_PIPENV_NOT_FOUND' + ); + } else { + throw e; + } + } +} /** * pipenv install @@ -28,31 +65,48 @@ async function pipfileToRequirements() { } try { - try { - await spawn('pipenv', ['lock', '--keep-outdated'], { - cwd: this.servicePath, - }); - } catch (e) { - const stderrBufferContent = - (e.stderrBuffer && e.stderrBuffer.toString()) || ''; + // Get and validate pipenv version + if (this.log) { + this.log.info('Getting pipenv version'); + } else { + this.serverless.cli.log('Getting pipenv version'); + } + + const pipenvVersion = await getPipenvVersion(); + let res; - if (stderrBufferContent.includes('must exist to use')) { - // No previous Pipfile.lock, we will try to generate it here - await spawn('pipenv', ['lock'], { + if (semver.gt(pipenvVersion, LEGACY_PIPENV_VERSION)) { + // Using new pipenv syntax ( >= 2022.8.13) + try { + await spawn('pipenv', ['lock', '--keep-outdated'], { cwd: this.servicePath, }); - } else if (stderrBufferContent.includes('command not found')) { - throw new this.serverless.classes.Error( - `pipenv not found! Install it according to the poetry docs.`, - 'PYTHON_REQUIREMENTS_PIPENV_NOT_FOUND' - ); - } else { - throw e; + } catch (e) { + const stderrBufferContent = + (e.stderrBuffer && e.stderrBuffer.toString()) || ''; + if (stderrBufferContent.includes('must exist to use')) { + // No previous Pipfile.lock, we will try to generate it here + await spawn('pipenv', ['lock'], { + cwd: this.servicePath, + }); + } else { + throw e; + } } + + res = await spawn('pipenv', ['requirements'], { + cwd: this.servicePath, + }); + } else { + // Falling back to legacy pipenv syntax + res = await spawn( + 'pipenv', + ['lock', '--requirements', '--keep-outdated'], + { + cwd: this.servicePath, + } + ); } - const res = await spawn('pipenv', ['requirements'], { - cwd: this.servicePath, - }); fse.ensureDirSync(path.join(this.servicePath, '.serverless')); fse.writeFileSync( diff --git a/package.json b/package.json index 1aeeb4e5..318eec59 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "lodash.uniqby": "^4.7.0", "lodash.values": "^4.3.0", "rimraf": "^3.0.2", + "semver": "^7.3.8", "set-value": "^4.1.0", "sha256-file": "1.0.0", "shell-quote": "^1.7.4"