name: PMG E2E Tests on: pull_request: branches: - main push: branches: - main workflow_dispatch: permissions: contents: read jobs: e2e-test: name: PMG E2E Tests - All Package Managers runs-on: ${{ matrix.os }} timeout-minutes: 20 strategy: fail-fast: false matrix: os: [ubuntu-latest] defaults: run: shell: bash steps: - name: Checkout Source uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Setup Go uses: actions/setup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b # v5 with: go-version-file: go.mod - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: 20 check-latest: true - name: Setup PNPM uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 with: version: 10 - name: Setup Bun uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2 with: bun-version: latest - name: Setup Python uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: "3.11" - name: Setup uv uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 - name: Install Poetry uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a - name: Build PMG run: make - name: Add pmg to PATH run: echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH - name: Setup PMG run: pmg setup install - name: Test PMG - Config File is Created run: | test -f $HOME/.config/safedep/pmg/config.yml - name: Test pmg.rc File is Created run: | test -f $HOME/.pmg.rc - name: Test NPM - Single Package & Manifest run: | echo "Testing NPM single package installation..." mkdir npm-test && cd npm-test pmg npm init -y pmg npm install express@5.2.1 pmg npm install lodash@4.17.21 # Verification: npm added packages present and manifest updated test -d node_modules/express test -d node_modules/lodash grep -q '"express"' package.json grep -q '"lodash"' package.json echo "Testing NPM manifest installation..." rm -rf node_modules package-lock.json pmg npm install # Verification: npm lockfile and installed modules exist after manifest install test -f package-lock.json test -d node_modules/express test -d node_modules/lodash cd .. && rm -rf npm-test - name: Test NPM - Experimental Proxy Mode run: | echo "Testing NPM with experimental proxy-based interception..." mkdir npm-proxy-test && cd npm-proxy-test pmg npm init -y echo "Testing proxy mode single package installation..." pmg --experimental-proxy-mode npm install express@5.2.1 pmg --experimental-proxy-mode npm install lodash@4.17.21 # Verification: packages installed via proxy mode test -d node_modules/express test -d node_modules/lodash grep -q '"express"' package.json grep -q '"lodash"' package.json echo "Testing proxy mode manifest installation..." rm -rf node_modules package-lock.json pmg --experimental-proxy-mode npm install # Verification: manifest install via proxy mode works test -f package-lock.json test -d node_modules/express test -d node_modules/lodash echo "Testing proxy mode with scoped package..." pmg --experimental-proxy-mode npm install @types/node@18.0.0 # Verification: scoped package installed via proxy test -d node_modules/@types test -d node_modules/@types/node grep -q '"@types/node"' package.json echo "Testing proxy mode dry-run (should not create files)..." rm -rf node_modules package-lock.json pmg --experimental-proxy-mode --dry-run npm install # Verification: dry-run doesn't create files even in proxy mode test ! -d node_modules test ! -f package-lock.json cd .. && rm -rf npm-proxy-test - name: Test PNPM - Single Package & Manifest run: | echo "Testing PNPM single package installation..." mkdir pnpm-test && cd pnpm-test pmg pnpm init pmg pnpm add express@5.2.1 pmg pnpm add lodash@4.17.21 # Verification: pnpm packages installed and lockfile created test -d node_modules/express test -d node_modules/lodash test -f pnpm-lock.yaml echo "Testing PNPM manifest installation..." rm -rf node_modules pnpm-lock.yaml pmg pnpm install # Verification: pnpm lockfile and modules exist after manifest install test -f pnpm-lock.yaml test -d node_modules/express test -d node_modules/lodash cd .. && rm -rf pnpm-test - name: Test Bun - Single Package & Manifest run: | echo "Testing Bun single package installation..." mkdir bun-test && cd bun-test pmg bun init -y pmg bun add express@5.2.1 pmg bun add lodash@4.17.21 # Verification: bun packages installed and lockfile created test -d node_modules/express test -d node_modules/lodash test -f bun.lock echo "Testing Bun manifest installation..." rm -rf node_modules bun.lock pmg bun install # Verification: bun lockfile and modules exist after manifest install test -f bun.lock test -d node_modules/express test -d node_modules/lodash cd .. && rm -rf bun-test - name: Test Yarn - Single Package & Manifest run: | echo "Testing Yarn single package installation..." export YARN_ENABLE_HARDENED_MODE=0 npm install -g yarn@1.22.22 yarn --version mkdir yarn-test && cd yarn-test pmg yarn init -y pmg yarn add express@5.2.1 pmg yarn add lodash@4.17.21 # Verification: yarn packages installed and lockfile created test -d node_modules/express test -d node_modules/lodash test -f yarn.lock echo "Testing Yarn manifest installation..." rm -rf node_modules yarn.lock pmg yarn install # Verification: yarn lockfile and modules exist after manifest install test -f yarn.lock test -d node_modules/express test -d node_modules/lodash cd .. && rm -rf yarn-test - name: Test Pip - Single Package & Manifest run: | echo "Testing Pip single package installation..." mkdir pip-test && cd pip-test python -m venv venv && source venv/bin/activate pmg pip install requests==2.32.4 pmg pip install numpy==2.3.5 pmg pip freeze > requirements.txt # Verification: requirements.txt contains expected packages test -s requirements.txt grep -E '^requests==' requirements.txt grep -E '^numpy==' requirements.txt echo "Testing Pip manifest installation..." pmg pip uninstall -y requests numpy pmg pip install -r requirements.txt # Verification: imported packages are available in the environment python -c "import requests, numpy; print(requests.__version__); print(numpy.__version__)" deactivate cd .. && rm -rf pip-test - name: Test Pip3 - Single Package & Manifest run: | echo "Testing Pip3 single package installation..." mkdir pip3-test && cd pip3-test python -m venv venv && source venv/bin/activate pmg pip3 install requests==2.32.4 pmg pip3 install numpy==2.3.5 pmg pip3 freeze > requirements.txt # Verification: requirements.txt contains expected packages test -s requirements.txt grep -E '^requests==' requirements.txt grep -E '^numpy==' requirements.txt echo "Testing Pip3 manifest installation..." pmg pip3 uninstall -y requests numpy pmg pip3 install -r requirements.txt # Verification: imported packages are available in the environment python -c "import requests, numpy; print(requests.__version__); print(numpy.__version__)" deactivate cd .. && rm -rf pip3-test - name: Test UV - Single Package & Manifest run: | echo "Testing UV single package installation..." mkdir uv-test && cd uv-test pmg uv init --no-readme pmg uv add requests==2.32.4 pmg uv add numpy==2.3.5 # Verification: pyproject.toml lists expected dependencies test -f pyproject.toml grep -q 'requests' pyproject.toml grep -q 'numpy' pyproject.toml echo "Testing UV manifest installation..." rm -rf .venv uv.lock pmg uv sync # Verification: uv lockfile and virtualenv created; packages present test -d .venv test -f uv.lock pmg uv pip show requests >/dev/null pmg uv pip show numpy >/dev/null echo "Testing UV pip commands..." pmg uv pip freeze > requirements.txt pmg uv pip install -r requirements.txt pmg uv pip sync requirements.txt # Verification: uv pip can show installed packages after requirements sync pmg uv pip show requests >/dev/null pmg uv pip show numpy >/dev/null cd .. && rm -rf uv-test - name: Test Poetry - Single Package & Manifest run: | echo "Testing Poetry single package installation..." mkdir poetry-test && cd poetry-test pmg poetry init --name poetry-test --no-interaction --quiet pmg poetry add requests==2.32.4 pmg poetry add numpy==2.3.5 # Verification: pyproject.toml dependencies updated test -f pyproject.toml grep -q 'requests' pyproject.toml grep -q 'numpy' pyproject.toml echo "Testing Poetry manifest installation..." rm -rf .venv poetry.lock pmg poetry install --no-root cd .. && rm -rf poetry-test - name: Test Malicious Package Detection run: | echo "Testing malicious package detection..." mkdir malicious-test && cd malicious-test pmg npm init -y ! pmg npm install nyc-config@10.0.0 || echo "Malicious package correctly blocked" cd .. && rm -rf malicious-test - name: Test PMG Modes run: | echo "Testing different PMG modes..." mkdir pmg-modes-test && cd pmg-modes-test pmg npm init -y # Mode: --dry-run should not create node_modules or lockfiles pmg --dry-run npm install express # Verification: no files created during dry-run test ! -d node_modules test ! -f package-lock.json # Mode: --silent should install without noisy output pmg --silent npm install express # Verification: package installed test -d node_modules/express # Clean and test --verbose installation rm -rf node_modules package-lock.json pmg --verbose npm install express # Verification: package installed test -d node_modules/express # Clean and test --debug with log output rm -rf node_modules package-lock.json pmg --debug --log debug.json npm install express # Verification: debug log written test -f debug.json # Mode: --paranoid may require cloud credentials; run non-blocking with dry-run pmg --paranoid --dry-run npm install express || true cd .. && rm -rf pmg-modes-test