# Examples

info

All command names are just examples, you will most likely have your own variant.

## Local Development

### 🍪 JavaScript (Vue, React, Angular, etc.)

Practically any web project contains `package.json` with scripts where various commands are described for building, running, and debugging locally. It looks something like this:

```json
...
  "scripts": {
    "serve": "vite",
...

```

1. Navigate to the project directory `cd ~/path/to/your/project`.
2. Set up the configuration for the project `tuna secrets setup`.
3. Edit `package.json` and add the `tuna secrets run` wrapper, it should look something like this:

```json
...
  "scripts": {
    "serve": "tuna secrets run --watch -- vite",
...

```

4. Run the application as usual `yarn serve` or `npm run serve`

***

### 🐹 Go (Golang)

Go projects are usually run through `go run` or `make`:

1. Navigate to the project directory `cd ~/path/to/your/project`.
2. Run `tuna secrets setup`.
3. Run the application with the wrapper:

```shell
tuna secrets run --watch -- go run ./cmd/server

```

Example Makefile:

```yaml
.DEFAULT_GOAL := run
.PHONY: run
run: ### Run
    @tuna secrets run --watch -- go run ./cmd/server

```

### 🦀 Rust (Rocket, Actix, etc.)

Rust projects most often use cargo:

1. Navigate to the project directory `cd ~/path/to/your/project`.
2. Run `tuna secrets setup`.
3. Run the application with the wrapper:

```shell
tuna secrets run --watch -- cargo run

```

Example Makefile:

```yaml
.DEFAULT_GOAL := run
.PHONY: run
run: ### Run
    @tuna secrets run --watch -- cargo run

```

***

### 🥠 Node.js server project (Express, Fastify, etc.)

Node.js backend also usually uses `package.json`, for example:

```json
...
  "scripts": {
    "dev": "node server.js",
...

```

1. Navigate to the project directory `cd ~/path/to/your/project`.
2. Set up the configuration for the project `tuna secrets setup`.
3. Edit `package.json`, adding the wrapper:

```json
...
  "scripts": {
    "dev": "tuna secrets run --watch -- node server.js",
...

```

4. Run the application `yarn dev` or `npm run dev`.

***

### 🐍 Python (Flask, Django, etc.)

Python projects are often run through `python`, `manage.py`, or `Makefile`.

1. Navigate to the project directory `cd ~/path/to/your/project`.
2. Set up the configuration for the project by adding the wrapper `tuna secrets setup`.
3. Wrap the run command:

```bash
tuna secrets run --watch -- python app.py

```

If you have Django:

```bash
tuna secrets run --watch -- python manage.py runserver

```

If you have a Makefile:

```yaml
.DEFAULT_GOAL := run
.PHONY: run
run: ### Run
    @tuna secrets run --watch -- python manage.py runserver

```

4. Run the application with this command.

***

### 🐘 PHP (Laravel, Symfony, etc.)

Usually the built-in PHP web server is used:

```shell
php -S localhost:8000 -t public

```

1. Navigate to the project directory `cd ~/path/to/your/project`.
2. Set up the configuration for the project `tuna secrets setup`.
3. Run the server through the `tuna secrets run` wrapper:

```bash
tuna secrets run --watch -- php -S localhost:8000 -t public

```

If you have Laravel:

```bash
tuna secrets run --watch -- php artisan serve

```

Example Makefile:

```yaml
.DEFAULT_GOAL := run
.PHONY: run
run: ### Run
    @tuna secrets run --watch -- php artisan serve

```

***

### ☕ Java/Kotlin (Spring Boot, Micronaut, etc.)

Such projects often use Gradle or Maven:

1. Navigate to the project directory `cd ~/path/to/your/project`.
2. Set up the configuration for the project `tuna secrets setup`.
3. Wrap the run command:

For Gradle:

```bash
tuna secrets run --watch -- ./gradlew bootRun

```

For Maven:

```bash
tuna secrets run --watch -- mvn spring-boot:run

```

Example Makefile:

```yaml
.DEFAULT_GOAL := run
.PHONY: run
run: ### Run
    @tuna secrets run --watch -- mvn spring-boot:run

```

4. Run the application as usual.

***

### 🪟 C#/.NET (ASP.NET Core, etc.)

.NET projects are run through `dotnet run`:

1. Navigate to the project directory `cd ~/path/to/your/project`.
2. Run `tuna secrets setup`.
3. Run the application with the wrapper:

```shell
tuna secrets run --watch -- dotnet run

```

Example Makefile (on Linux/macOS):

```yaml
.DEFAULT_GOAL := run
.PHONY: run
run: ### Run
    @tuna secrets run --watch -- dotnet run

```

***

## CI/CD

### 🦊 Gitlab CI

Create [service keys](https://tuna.am/en/docs/secrets.md#service-keys) for the required configurations and save the key in [Gitlab ci variables](https://docs.gitlab.com/ci/variables/). Suppose you have a project `myproj` with an environment `prod`, create a service key and save it to the variable `TUNA_API_KEY_MYPROJ_PROD` in Gitlab variables. Below is an example of how it might look in a Job:

**Environment variables**

```yaml
production:
  extends: [.base]
  environment:
    name: prod
  variables:
    TUNA_API_KEY: $TUNA_API_KEY_MYPROJ_PROD
    TUNA_SECRETS_PROJECT: $CI_PROJECT_NAME
    TUNA_SECRETS_CONFIG: $CI_ENVIRONMENT_NAME
    TUNA_SECRETS_FORMAT: env
    TUNA_SECRETS_NO_FILE: true
  before_script:
    - source <(tuna secrets download)
  script:
    - goreleaser release

```

**Flags**

```yaml
production:
  extends: [.base]
  environment:
    name: prod
  before_script:
    - source <(tuna --api-key=${TUNA_API_KEY_MYPROJ_PROD} secrets download --project=${CI_PROJECT_NAME} --config=${CI_ENVIRONMENT_NAME} --format=env --no-file)
  script:
    - goreleaser release

```

**The run wrapper**

```yaml
production:
  extends: [.base]
  environment:
    name: prod
  variables:
    TUNA_API_KEY: $TUNA_API_KEY_MYPROJ_PROD
    TUNA_SECRETS_PROJECT: $CI_PROJECT_NAME
    TUNA_SECRETS_CONFIG: $CI_ENVIRONMENT_NAME
  script:
    - tuna secrets run -- goreleaser release

```

The secrets only reach the process environment: no file in the working directory and no `source` in the job history. The exit code of `goreleaser` becomes the exit code of the job.

Note that **project** and **config** we get directly from the environment, this is possible if the project name in Gitlab and Tuna Secrets match, and also environment.name in Gitlab Job corresponds to the configuration alias.

***

### 🐙 GitHub Actions

Create [service keys](https://tuna.am/en/docs/secrets.md#service-keys) for the required configurations and save the key in [GitHub Secrets](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions). Suppose you have a project `myproj` with an environment `prod`, create a service key and save it to the variable `TUNA_API_KEY_MYPROJ_PROD` in GitHub Secrets. Below is an example of how it might look in a Job:

**Environment variables**

```yaml
name: Release

on:
  push:
    tags:
      - "v*"

jobs:
  production:
    runs-on: ubuntu-latest
    env:
      TUNA_API_KEY: ${{ secrets.TUNA_API_KEY_MYPROJ_PROD }}
      TUNA_SECRETS_PROJECT: ${{ github.event.repository.name }}
      TUNA_SECRETS_CONFIG: prod
      TUNA_SECRETS_FORMAT: env
      TUNA_SECRETS_NO_FILE: true
    steps:
      - uses: actions/checkout@v4
      - run: |
          source <(tuna secrets download)
          goreleaser release

```

**Flags**

```yaml
name: Release

on:
  push:
    tags:
      - "v*"

jobs:
  production:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          source <(tuna --api-key=${{ secrets.TUNA_API_KEY_MYPROJ_PROD }} secrets download --project=${{ github.event.repository.name }} --config=prod --format=env --no-file)
          goreleaser release


```

**The run wrapper**

```yaml
name: Release

on:
  push:
    tags:
      - "v*"

jobs:
  production:
    runs-on: ubuntu-latest
    env:
      TUNA_API_KEY: ${{ secrets.TUNA_API_KEY_MYPROJ_PROD }}
      TUNA_SECRETS_PROJECT: ${{ github.event.repository.name }}
      TUNA_SECRETS_CONFIG: prod
    steps:
      - uses: actions/checkout@v4
      - run: tuna secrets run -- goreleaser release

```

Note that `project = github.event.repository.name` we get directly from the environment, this is possible if the project name in GitHub and Tuna Secrets match, **config** is set explicitly.

***

### 🧰 Individual secrets in scripts

When a job needs a single secret, there is no point in exporting the whole config. The `--plain` flag prints the value without a trailing newline, so it is convenient to substitute right into a command:

```yaml
publish:
  script:
    - docker login -u "$CI_REGISTRY_USER" -p "$(tuna secrets get REGISTRY_PASSWORD --plain)" "$CI_REGISTRY"

```

The `-o json` flag is available on every command, including writes — which is exactly what scripts need:

```yaml
rotate-token:
  script:
    - openssl rand -hex 32 | tuna secrets set API_TOKEN
    - tuna secrets get API_TOKEN -o json | jq -r '.API_TOKEN.updated_at'

```

Rotation requires a service key with `write` access.

And here is a check that stage and prod did not end up with the same passwords. It works with [fingerprints](https://tuna.am/en/docs/secrets/cli.md#value-fingerprints) rather than values, so its result is safe to leave in the job log:

```yaml
check-secrets:
  script:
    - tuna secrets list -c stage -o json | jq -r 'to_entries[] | "\(.key) \(.value.fingerprint)"' > stage.txt
    - tuna secrets list -c prod  -o json | jq -r 'to_entries[] | "\(.key) \(.value.fingerprint)"' > prod.txt
    - comm -12 stage.txt prod.txt

```

***

### 🧵 Bitbucket Pipelines

Create [service keys](https://tuna.am/en/docs/secrets.md#service-keys) for the required configurations and save the key in [Bitbucket Pipelines variables](https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/). Suppose you have a project `myproj` with an environment `prod`, create a service key and save it to the variable `TUNA_API_KEY_MYPROJ_PROD` in Bitbucket Pipelines variables. Below is an example of how it might look in a Job:

**Environment variables**

```yaml
pipelines:
  tags:
    "v*":
      - step:
          name: Production Build
          deployment: prod
          script:
            - export TUNA_API_KEY=$TUNA_API_KEY_MYPROJ_PROD
            - export TUNA_SECRETS_PROJECT=$BITBUCKET_REPO_SLUG
            - export TUNA_SECRETS_CONFIG=prod
            - export TUNA_SECRETS_FORMAT=env
            - export TUNA_SECRETS_NO_FILE=true
            - source <(tuna secrets download)
            - goreleaser release


```

**Flags**

```yaml
pipelines:
  tags:
    "v*":
      - step:
          name: Release
          deployment: prod
          script:
            - source <(tuna --api-key=$TUNA_API_KEY_MYPROJ_PROD secrets download --project=$BITBUCKET_REPO_SLUG --config=prod) --format=env --no-file)
            - goreleaser release


```

Note that `project = $BITBUCKET_REPO_SLUG` we get directly from the environment, this is possible if the project name in `BITBUCKET_REPO_SLUG` and Tuna Secrets match, **config** is set explicitly.
