diff --git a/.github/workflows/release_build_infisical_cli.yml b/.github/workflows/release_build_infisical_cli.yml index 02c3492376..3a3b384f39 100644 --- a/.github/workflows/release_build_infisical_cli.yml +++ b/.github/workflows/release_build_infisical_cli.yml @@ -10,8 +10,7 @@ on: permissions: contents: write - # packages: write - # issues: write + jobs: cli-integration-tests: name: Run tests before deployment @@ -26,6 +25,63 @@ jobs: CLI_TESTS_USER_PASSWORD: ${{ secrets.CLI_TESTS_USER_PASSWORD }} CLI_TESTS_INFISICAL_VAULT_FILE_PASSPHRASE: ${{ secrets.CLI_TESTS_INFISICAL_VAULT_FILE_PASSPHRASE }} + npm-release: + runs-on: ubuntu-20.04 + env: + working-directory: ./npm + needs: + - cli-integration-tests + - goreleaser + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Extract version + run: | + VERSION=$(echo ${{ github.ref_name }} | sed 's/infisical-cli\/v//') + echo "Version extracted: $VERSION" + echo "CLI_VERSION=$VERSION" >> $GITHUB_ENV + + - name: Print version + run: echo ${{ env.CLI_VERSION }} + + - name: Setup Node + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 + with: + node-version: 20 + cache: "npm" + cache-dependency-path: ./npm/package-lock.json + - name: Install dependencies + working-directory: ${{ env.working-directory }} + run: npm install --ignore-scripts + + - name: Set NPM version + working-directory: ${{ env.working-directory }} + run: npm version ${{ env.CLI_VERSION }} --allow-same-version --no-git-tag-version + + - name: Setup NPM + working-directory: ${{ env.working-directory }} + run: | + echo 'registry="https://registry.npmjs.org/"' > ./.npmrc + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ./.npmrc + + echo 'registry="https://registry.npmjs.org/"' > ~/.npmrc + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Pack NPM + working-directory: ${{ env.working-directory }} + run: npm pack + + - name: Publish NPM + working-directory: ${{ env.working-directory }} + run: npm publish --tarball=./infisical-sdk-${{github.ref_name}} --access public --registry=https://registry.npmjs.org/ + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + goreleaser: runs-on: ubuntu-20.04 needs: [cli-integration-tests] diff --git a/.gitignore b/.gitignore index e76fd0c11b..f2a23324b8 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,5 @@ frontend-build cli/infisical-merge cli/test/infisical-merge /backend/binary + +/npm/bin diff --git a/docs/cli/overview.mdx b/docs/cli/overview.mdx index ab913ec1af..397d1f474f 100644 --- a/docs/cli/overview.mdx +++ b/docs/cli/overview.mdx @@ -9,7 +9,7 @@ You can use it across various environments, whether it's local development, CI/C ## Installation - + Use [brew](https://brew.sh/) package manager ```bash @@ -21,9 +21,8 @@ You can use it across various environments, whether it's local development, CI/C ```bash brew update && brew upgrade infisical ``` - - - + + Use [Scoop](https://scoop.sh/) package manager ```bash @@ -40,7 +39,20 @@ You can use it across various environments, whether it's local development, CI/C scoop update infisical ``` - + + + Use [NPM](https://www.npmjs.com/) package manager + + ```bash + npm install -g @infisical/cli + ``` + + ### Updates + + ```bash + npm update -g @infisical/cli + ``` + Install prerequisite ```bash diff --git a/npm/.eslintrc.json b/npm/.eslintrc.json new file mode 100644 index 0000000000..de8743bbbf --- /dev/null +++ b/npm/.eslintrc.json @@ -0,0 +1,9 @@ +{ + "env": { + "es6": true, + "node": true + }, + "parserOptions": { + "ecmaVersion": "latest" + } +} diff --git a/npm/README.md b/npm/README.md new file mode 100644 index 0000000000..b64b02ccde --- /dev/null +++ b/npm/README.md @@ -0,0 +1,71 @@ +

Infisical

+

+

The open-source secret management platform: Sync secrets/configs across your team/infrastructure and prevent secret leaks.

+

+ +

+ Slack | + Infisical Cloud | + Self-Hosting | + Docs | + Website | + Hiring (Remote/SF) +

+ + +

+ + Infisical is released under the MIT license. + + + PRs welcome! + + + git commit activity + + + Cloudsmith downloads + + + Slack community channel + + + Infisical Twitter + +

+ +### Introduction + +**[Infisical](https://infisical.com)** is the open source secret management platform that teams use to centralize their application configuration and secrets like API keys and database credentials as well as manage their internal PKI. + +We're on a mission to make security tooling more accessible to everyone, not just security teams, and that means redesigning the entire developer experience from ground up. + + +### Installation + +The Infisical CLI NPM package serves as a new installation method in addition to our [existing installation methods](https://infisical.com/docs/cli/overview). + +After installing the CLI with the command below, you'll be able to use the infisical CLI across your machine. + +```bash +$ npm install -g @infisical/cli +``` + +Full example: +```bash +# Install the Infisical CLI +$ npm install -g @infisical/cli + +# Authenticate with the Infisical CLI +$ infisical login + +# Initialize your Infisical CLI +$ infisical init + +# List your secrets with Infisical CLI +$ infisical secrets +``` + + +### Documentation +Our full CLI documentation can be found [here](https://infisical.com/docs/cli/usage). \ No newline at end of file diff --git a/npm/package-lock.json b/npm/package-lock.json new file mode 100644 index 0000000000..872adcf77c --- /dev/null +++ b/npm/package-lock.json @@ -0,0 +1,112 @@ +{ + "name": "@infisical/cli", + "version": "0.14.3", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@infisical/cli", + "version": "0.14.3", + "hasInstallScript": true, + "dependencies": { + "tar": "^6.2.0" + }, + "bin": { + "infisical": "bin/infisical" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/npm/package.json b/npm/package.json new file mode 100644 index 0000000000..31859c5988 --- /dev/null +++ b/npm/package.json @@ -0,0 +1,25 @@ +{ + "name": "@infisical/cli", + "private": false, + "version": "0.0.0", + "keywords": [ + "infisical", + "cli", + "command-line" + ], + "bin": { + "infisical": "./bin/infisical" + }, + "repository": { + "type": "git", + "url": "https://github.com/Infisical/infisical.git" + }, + "author": "Infisical Inc, ", + + "scripts": { + "postinstall": "node src/index.cjs" + }, + "dependencies": { + "tar": "^6.2.0" + } +} diff --git a/npm/src/index.cjs b/npm/src/index.cjs new file mode 100644 index 0000000000..28fe0979b9 --- /dev/null +++ b/npm/src/index.cjs @@ -0,0 +1,103 @@ +const childProcess = require("child_process"); +const fs = require("fs"); +const stream = require("node:stream"); +const tar = require("tar"); +const path = require("path"); +const zlib = require("zlib"); +const packageJSON = require("../package.json"); + +const supportedPlatforms = ["linux", "darwin", "win32", "freebsd"]; +const outputDir = "bin"; + +const getPlatform = () => { + const platform = process.platform; + if (!supportedPlatforms.includes(platform)) { + console.error("Your platform doesn't seem to be of type darwin, linux or windows"); + process.exit(1); + } + return platform; +}; + +const getArchitecture = () => { + const architecture = process.arch; + let arch = ""; + + if (architecture === "x64" || architecture === "amd64") { + arch = "amd64"; + } else if (architecture === "arm64") { + arch = "arm64"; + } else if (architecture === "arm") { + // If the platform is Linux, we should find the exact ARM version, otherwise we default to armv7 which is the most common + if (process.platform === "linux" || process.platform === "freebsd") { + const output = childProcess.execSync("uname -m").toString().trim(); + + const armVersions = ["armv5", "armv6", "armv7"]; + + const armVersion = armVersions.find(version => output.startsWith(version)); + + if (armVersion) { + arch = armVersion; + } else { + arch = "armv7"; + } + } else { + arch = "armv7"; + } + } else if (architecture === "ia32") { + arch = "i386"; + } else { + console.error("Your architecture doesn't seem to be supported. Your architecture is", architecture); + process.exit(1); + } + + return arch; +}; + +async function main() { + const PLATFORM = getPlatform(); + const ARCH = getArchitecture(); + const NUMERIC_RELEASE_VERSION = packageJSON.version; + const LATEST_RELEASE_VERSION = `v${NUMERIC_RELEASE_VERSION}`; + const downloadLink = `https://github.com/Infisical/infisical/releases/download/infisical-cli/${LATEST_RELEASE_VERSION}/infisical_${NUMERIC_RELEASE_VERSION}_${PLATFORM}_${ARCH}.tar.gz`; + + // Ensure the output directory exists + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir); + } + + // Download the latest CLI binary + try { + const response = await fetch(downloadLink, { + headers: { + Accept: "application/octet-stream" + } + }); + + if (!response.ok) { + throw new Error(`Failed to fetch: ${response.status} - ${response.statusText}`); + } + + await new Promise((resolve, reject) => { + const outStream = stream.Readable.fromWeb(response.body) + .pipe(zlib.createGunzip()) + .pipe( + tar.x({ + C: path.join(outputDir), + filter: path => path === "infisical" + }) + ); + + outStream.on("error", reject); + outStream.on("close", resolve); + }); + + // Give the binary execute permissions if we're not on Windows + if (PLATFORM !== "win32") { + fs.chmodSync(path.join(outputDir, "infisical"), "755"); + } + } catch (error) { + console.error("Error downloading or extracting Infisical CLI:", error); + process.exit(1); + } +} +main();