Skip to content

Commit

Permalink
Merge branch 'develop' into Cli_invitationList
Browse files Browse the repository at this point in the history
  • Loading branch information
rajdip-b authored Jan 22, 2025
2 parents 1696b5c + d1bc740 commit 64e2568
Show file tree
Hide file tree
Showing 61 changed files with 4,318 additions and 4,759 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ PLATFORM_OAUTH_FAILURE_REDIRECT_PATH=/oauth/failure
DOMAIN=localhost
FEEDBACK_FORWARD_EMAIL=

BACKEND_URL=http://localhost:4200
NEXT_PUBLIC_BACKEND_URL=http://localhost:4200
NEXT_PUBLIC_GOOGLE_ANALYTICS_MEASUREMENT_ID=

NODE_ENV=dev

Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/deploy-web.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ jobs:
REPOSITORY_NAME: web
run: |
# Build a docker container and push it to ACR
docker build -t $ACR_REGISTRY_URL/$REPOSITORY_NAME:${GITHUB_SHA::6} -t $ACR_REGISTRY_URL/$REPOSITORY_NAME:latest -f ./apps/web/Dockerfile .
docker build \
-t $ACR_REGISTRY_URL/$REPOSITORY_NAME:${GITHUB_SHA::6} \
-t $ACR_REGISTRY_URL/$REPOSITORY_NAME:latest \
--build-arg NEXT_PUBLIC_GOOGLE_ANALYTICS_MEASUREMENT_ID=$NEXT_PUBLIC_GOOGLE_ANALYTICS_MEASUREMENT_ID \
-f ./apps/web/Dockerfile .
echo "Pushing image to ACR..."
docker push $ACR_REGISTRY_URL/$REPOSITORY_NAME:latest
docker push $ACR_REGISTRY_URL/$REPOSITORY_NAME:${GITHUB_SHA::6}
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@

<div align = "center">

[![keyshade.xyz Discord](https://dcbadge.vercel.app/api/server/m6TcpWBSdt)](https://discord.gg/acfN4k6dxU)
<a href="https://discord.gg/acfN4k6dxU"><img src="https://img.shields.io/badge/Discord-7289DA?style=for-the-badge&logo=discord&logoColor=white" /></a>
<a href="https://twitter.com/keyshade_xyz"><img src="https://img.shields.io/badge/X-000000?style=for-the-badge&logo=x&logoColor=white" /></a>
<a href="https://www.linkedin.com/company/keyshade-xyz/"><img src="https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white" /></a>

</div>

<p align="center>

<a href="https://www.producthunt.com/posts/keyshade?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-keyshade" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=436664&theme=light" alt="keyshade - Manage&#0032;all&#0032;your&#0032;secrets&#0032;securely | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
<div align="center>

<a href="https://www.producthunt.com/posts/keyshade?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-keyshade" target="_blank">
<img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=436664&theme=light" alt="keyshade - Manage&#0032;all&#0032;your&#0032;secrets&#0032;securely | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" />
</a>

</p>
</div>

---

Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/project/project.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1416,7 +1416,7 @@ describe('Project Controller Tests', () => {
expect(devEnvironment.name).toBe(environment.name)

expect(defaultEnvironment).toBeDefined()
expect(defaultEnvironment.name).toBe('Default')
expect(defaultEnvironment.name).toBe('default')
})

it('should only copy new environments, secrets and variables if sync is not hard', async () => {
Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/project/service/project.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,9 @@ export class ProjectService {
createEnvironmentOps.push(
this.prisma.environment.create({
data: {
name: 'Default',
name: 'default',
slug: await generateEntitySlug(
'Default',
'default',
'ENVIRONMENT',
this.prisma
),
Expand Down
15 changes: 15 additions & 0 deletions apps/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,18 @@

- Listing of environments and secrets made better
- Fixed incorrect error message while listing projects

## 2.4.0

### Minor Changes

- Profile name creation now supports \_ and - characters
- Polished the README file
- Support to specify environment name and description while creating a project
- Profile creation prompts users for all values if no option is set and shows default values
- Commands invoking API endpoints first check if the backend is reachable before executing the command

## Patches

- Fixed error when the CLI won't create `.keyshade` folder while initializing profiles on new devices
- Projects always had `--store-private-key` set to true despite providing a false value. Fixed this.
52 changes: 52 additions & 0 deletions apps/cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<div align="center">
<a href="https://keyshade.xyz/">
<img src="https://github.com/user-attachments/assets/a40b8d80-f55f-43d1-bc12-3363f320dabc" />
</a>
</div>

<br/>

<p align="center">
<a href="https://www.keyshade.xyz?ref=github" target="_blank"><b>Website</b></a> •
<a href="https://docs.keyshade.xyz/" target="_blank"><b>Documentation</b></a> •
<a href="https://discord.gg/dh8F3Dzt" target="_blank"><b>Join our Community</b></a> •
<a href="https://twitter.com/keyshade_xyz" target="_blank"><b>Twitter</b></a> •
<a href="https://www.linkedin.com/company/keyshade-xyz/" target="_blank"><b>LinkedIn</b></a>
</p>

<br/>

<div align="center">

[![Coverage Status](https://codecov.io/gh/keyshade-xyz/keyshade/branch/develop/graph/badge.svg)](https://app.codecov.io/gh/keyshade-xyz/keyshade)
[![Build Status](https://github.com/keyshade-xyz/keyshade/actions/workflows/deploy-cli.yml/badge.svg?branch=master)](https://github.com/keyshade-xyz/keyshade/actions/workflows/deploy-cli.yml)
[![npm version](https://img.shields.io/npm/v/@keyshade/cli.svg)](https://www.npmjs.com/package/@keyshade/cli?activeTab=versions)
[![license](https://img.shields.io/github/license/keyshade-xyz/keyshade.svg)](https://github.com/keyshade-xyz/keyshade/blob/develop/LICENSE)

</div>

---

> ⚠️ Warning: This is a closed alpha version and is not intended for public use at this time.
---

# Keyshade Command Line Inteface

Keyshade CLI is a powerful command-line tool for managing secrets and configuration in your projects. Designed for developers, it helps you detect secret sprawl, securely manage sensitive information, and integrate seamlessly into your development workflow.

## Features
- **Secret Sprawl Detection**: Identify and prevent sensitive data leaks.
- **Live Secret Update**: Instantly propagate secret changes across your applications without redeployment.
- **Secrets Management**: Securely store, retrieve, and rotate secrets.
- **Full Platform Parity**: Perform almost everything with the CLI that you can do with the Keyshade platform.

## Installation
Install Keyshade CLI using npm:
```sh
npm install -g @keyshade/cli
```
Verify the installation using:
```sh
keyshade --help
```
19 changes: 17 additions & 2 deletions apps/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@keyshade/cli",
"version": "2.3.0",
"version": "2.4.0",
"description": "CLI for keyshade",
"main": "dist/index.cjs",
"module": "dist/index.esm.js",
Expand All @@ -20,7 +20,22 @@
"lint": "eslint \"src/**/*.ts\" --fix",
"publish": "pnpm build && pnpm publish --access public --provenance"
},
"keywords": [],
"keywords": [
"keyshade",
"keyshade cli",
"secret",
"secrets",
"secret management",
"secret manager",
"config management",
"config manager",
"secret management tool",
"config management tool",
"configuration",
"devsecops",
"secret scanning",
"secret detection"
],
"author": "keyshade",
"license": "MPL-2.0",
"dependencies": {
Expand Down
20 changes: 16 additions & 4 deletions apps/cli/src/commands/base.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,22 @@ export default abstract class BaseCommand {
const globalOptions = program.optsWithGlobals()
await this.setGlobalContextFields(globalOptions)

if (this.canMakeHttpRequests() && !this.apiKey) {
throw new Error(
'API key is missing. This command requires an API key. Either specify it using --api-key, or send in a profile using --profile, or set a default profile'
)
if (this.canMakeHttpRequests()) {
if (!this.apiKey) {
throw new Error(
'API key is missing. This command requires an API key. Either specify it using --api-key, or send in a profile using --profile, or set a default profile'
)
}

try {
await ControllerInstance.getInstance().appController.health(
this.headers
)
} catch {
throw new Error(
`Could not connect to the server: ${this.baseUrl}.`
)
}
}

const commandOptions = data[argsCount]
Expand Down
4 changes: 4 additions & 0 deletions apps/cli/src/commands/environment/create.environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export class CreateEnvironment extends BaseCommand {
]
}

canMakeHttpRequests(): boolean {
return true
}

async action({ options, args }: CommandActionData): Promise<void> {
const [projectSlug] = args
const { name, description } = await this.parseInput(options)
Expand Down
4 changes: 4 additions & 0 deletions apps/cli/src/commands/environment/delete.environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export class DeleteEnvironment extends BaseCommand {
]
}

canMakeHttpRequests(): boolean {
return true
}

async action({ args }: CommandActionData): Promise<void> {
const [environmentSlug] = args

Expand Down
4 changes: 4 additions & 0 deletions apps/cli/src/commands/environment/get.environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export class GetEnvironment extends BaseCommand {
]
}

canMakeHttpRequests(): boolean {
return true
}

async action({ args }: CommandActionData): Promise<void> {
const [environmentSlug] = args

Expand Down
4 changes: 4 additions & 0 deletions apps/cli/src/commands/environment/list.environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export class ListEnvironment extends BaseCommand {
return PAGINATION_OPTION
}

canMakeHttpRequests(): boolean {
return true
}

async action({ args, options }: CommandActionData): Promise<void> {
const [projectSlug] = args

Expand Down
4 changes: 4 additions & 0 deletions apps/cli/src/commands/environment/update.environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export class UpdateEnvironment extends BaseCommand {
]
}

canMakeHttpRequests(): boolean {
return true
}

async action({ options, args }: CommandActionData): Promise<void> {
const [environmentSlug] = args
const { name, description } = options
Expand Down
44 changes: 36 additions & 8 deletions apps/cli/src/commands/profile/create.profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,32 +82,60 @@ export default class CreateProfile extends BaseCommand {
}> {
let { name, apiKey, baseUrl, setDefault, enableMetrics } = options

if (!name) {
if (
!name &&
!apiKey &&
!baseUrl &&
setDefault == null &&
enableMetrics == null
) {
name = await text({
message: 'Enter the name of the profile',
placeholder: 'work'
})
}

if (!apiKey) {
apiKey = await text({
message: 'Enter the API key for the profile',
placeholder: 'ks_************'
})
}

if (!enableMetrics === undefined) {
baseUrl =
(await text({
message: `Enter the base URL for the keyshade server (default: ${API_BASE_URL})`,
placeholder: API_BASE_URL
})) || API_BASE_URL

setDefault = await confirm({
message: 'Set the profile as the default profile?',
initialValue: false
})

enableMetrics = await confirm({
message: 'Should keyshade collect anonymous metrics for development?'
message: 'Should keyshade collect anonymous metrics for development?',
initialValue: false
})
} else {
if (!name) {
name = await text({
message: 'Enter the name of the profile',
placeholder: 'work'
})
}

if (!apiKey) {
apiKey = await text({
message: 'Enter the API key for the profile',
placeholder: 'ks_************'
})
}
}

const inputSchema = z.object({
name: z
.string()
.regex(
/^[a-zA-Z0-9]+$/,
'Name must contain only letters and numbers without spaces.'
/^[a-zA-Z0-9_-]+$/,
'Name must contain only letters, numbers, hyphens, and underscores without spaces.'
),
apiKey: z
.string()
Expand Down
43 changes: 39 additions & 4 deletions apps/cli/src/commands/project/create.project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,41 @@ export default class CreateProject extends BaseCommand {
{
short: '-k',
long: '--store-private-key',
description: 'Store the private key in the project. Defaults to true',
defaultValue: true
description: 'Store the private key in the project.'
},
{
short: '-a',
long: '--access-level <string>',
description: 'Access level of the project. Defaults to PRIVATE.',
defaultValue: 'PRIVATE',
choices: ['GLOBAL', 'PRIVATE', 'INTERNAL']
},
{
short: '-e',
long: '--environment <string...>',
description: `Should be in the format <name(mandatory)>[:<description>(optional)]
Examples:
$ keyshade [...]
-> { name: "Default", description: ". . ." }
$ keyshade [...] -e "dev"
-> { name: "dev", description: NULL }
$ keyshade [...] -e "dev:sample env"
-> { name: "dev", description: "sample env" }
$ keyshade [...] -e " dev : surrounding blank spaces "
-> { name: "dev", description: "surrounding blank spaces" }
`
}
]
}

canMakeHttpRequests(): boolean {
return true
}

async action({ args, options }: CommandActionData): Promise<void> {
const [workspaceSlug] = args

Expand Down Expand Up @@ -86,9 +108,12 @@ export default class CreateProject extends BaseCommand {
description?: string
storePrivateKey: boolean
accessLevel: 'PRIVATE' | 'GLOBAL' | 'INTERNAL'
environments: Array<{ name: string; description?: string }> | undefined
}> {
let { name, description } = options
const { storePrivateKey, accessLevel } = options
const { storePrivateKey, accessLevel, environment } = options

let environments: Array<{ name: string; description?: string }> | undefined

if (!name) {
name = await text({
Expand All @@ -101,6 +126,16 @@ export default class CreateProject extends BaseCommand {
description = name
}

return { name, description, storePrivateKey, accessLevel }
if (environment) {
environments = environment.map((env: string) => {
const split = env.split(':')
return {
name: split[0].trim(),
description: split[1]?.trim() ?? null
}
})
}

return { name, description, storePrivateKey, accessLevel, environments }
}
}
Loading

0 comments on commit 64e2568

Please sign in to comment.