Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Environment variables article #21

Merged
merged 3 commits into from Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions docs/index.html
Expand Up @@ -68,6 +68,19 @@ <h1>Swift on server</h1>

<div class="grid">
<div class="post">
<a href="https://swiftonserver.com/using-environment-variables-in-swift/" target="">
<section>
<time datetime="2024/03/12">2024/03/12</time>
<h2 class="Using environment variables in Swift">Using environment variables in Swift</h2>
<p>Explore the importance of environment variables in Swift and how to use them.</p>
<div class="meta">
<span class="tag">Swift</span>
<span class="tag">Environment</span>
</div>
</section>
</a>
</div>
<div class="post">
<a href="https://swiftonserver.com/using-openapi-with-hummingbird/" target="">
<section>
<time datetime="2024/03/05">2024/03/05</time>
Expand Down
11 changes: 9 additions & 2 deletions docs/rss.xml
Expand Up @@ -4,11 +4,18 @@
<description>Articles about server-side Swift development. Created by Joannis Orlandos and Tibor Bödecs.</description>
<link>https://swiftonserver.com/</link>
<language>en-US</language>
<lastBuildDate>Tue, 05 Mar 2024 09:49:41 +0000</lastBuildDate>
<pubDate>Mon, 04 Mar 2024 23:00:00 +0000</pubDate>
<lastBuildDate>Tue, 12 Mar 2024 13:05:24 +0000</lastBuildDate>
<pubDate>Mon, 11 Mar 2024 23:00:00 +0000</pubDate>
<ttl>250</ttl>
<atom:link href="https://swiftonserver.com/rss.xml" rel="self" type="application/rss+xml"/>

<item>
<guid isPermaLink="true">https://swiftonserver.com/using-environment-variables-in-swift/</guid>
<title><![CDATA[ Using environment variables in Swift ]]></title>
<description><![CDATA[ Explore the importance of environment variables in Swift and how to use them. ]]></description>
<link>https://swiftonserver.com/using-environment-variables-in-swift/</link>
<pubDate>Mon, 11 Mar 2024 23:00:00 +0000</pubDate>
</item>
<item>
<guid isPermaLink="true">https://swiftonserver.com/using-openapi-with-hummingbird/</guid>
<title><![CDATA[ Using OpenAPI Generator with Hummingbird ]]></title>
Expand Down
24 changes: 14 additions & 10 deletions docs/sitemap.xml
@@ -1,30 +1,34 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://swiftonserver.com/using-environment-variables-in-swift/</loc>
<lastmod>2024-03-12</lastmod>
</url>
<url>
<loc>https://swiftonserver.com/logging-for-server-side-swift-apps/</loc>
<lastmod>2024-03-12</lastmod>
</url>
<url>
<loc>https://swiftonserver.com/using-openapi-with-hummingbird/</loc>
<lastmod>2024-03-05</lastmod>
<lastmod>2024-03-12</lastmod>
</url>
<url>
<loc>https://swiftonserver.com/whats-new-in-hummingbird-2/</loc>
<lastmod>2024-03-01</lastmod>
<lastmod>2024-03-12</lastmod>
</url>
<url>
<loc>https://swiftonserver.com/building-swiftnio-clients/</loc>
<lastmod>2024-03-01</lastmod>
</url>
<url>
<loc>https://swiftonserver.com/logging-for-server-side-swift-apps/</loc>
<lastmod>2024-03-01</lastmod>
<lastmod>2024-03-12</lastmod>
</url>
<url>
<loc>https://swiftonserver.com/using-swiftnio-channels/</loc>
<lastmod>2024-03-01</lastmod>
<lastmod>2024-03-12</lastmod>
</url>
<url>
<loc>https://swiftonserver.com/using-swiftnio-fundamentals/</loc>
<lastmod>2024-03-01</lastmod>
<lastmod>2024-03-12</lastmod>
</url>
<url>
<loc>https://swiftonserver.com/developing-with-swift-in-visual-studio-code/</loc>
<lastmod>2024-03-01</lastmod>
<lastmod>2024-03-12</lastmod>
</url>
</urlset>
215 changes: 215 additions & 0 deletions docs/using-environment-variables-in-swift/index.html

Large diffs are not rendered by default.

Expand Up @@ -6,9 +6,9 @@ date: 2024/02/13
tags: Swift, Logging, Observability
author: Tibor Bödecs
authorLink: https://x.com/tiborbodecs
authorGithub: tib
company: Binary Birds Kft.
companyLink: https://binarybirds.com/
authorGithub: tib
duration: 20 minutes
sample: https://github.com/swift-on-server/logging-for-server-side-swift-apps-sample
---
Expand Down
@@ -0,0 +1,213 @@
---
slug: using-environment-variables-in-swift
title: Using environment variables in Swift
description: Explore the importance of environment variables in Swift and how to use them.
date: 2024/03/12
tags: Swift, Environment
author: Tibor Bödecs
authorLink: https://x.com/tiborbodecs
authorGithub: tib
company: Binary Birds Kft.
companyLink: https://binarybirds.com/
duration: 5 minutes
---

Environment variables are key-value pairs that can be used to alter the behavior of an application. The variables are part of the environment in which a process runs. The environment is injected during the runtime of the application. Environment variables can be set at the system level or they can be defined by the end-user.

Environment variables are commonly used for configuration purposes. It is possible to set different configuration values for development, testing and production environment. It is possible to use env vars as feature flags or to specify secrets and keys and keep them separate from the application codebase.

For example, an app could take advantage of the `LOG_LEVEL=trace` environment variable to set the log level using the [Logging library](https://swiftonserver.com/logging-for-server-side-swift-apps/) in Swift. By using an env variable developers can get more detailed logs for debugging purposes and less verbose logs for production without changing the source code of the application itself.


## How to access environment variables in Swift?

In Swift, it is possible to access environment variables using the [ProcessInfo](https://developer.apple.com/documentation/foundation/processinfo) class. The _ProcessInfo_ class is part of the Foundation framework.

Here's a quick example how to get the value of the `LOG_LEVEL` variable:

```swift
import Foundation

let env = ProcessInfo.processInfo.environment

let value = env["LOG_LEVEL"] ?? "trace"

print(value)
```

The process info's environment is represented a `[String: String]` dictionary. When requesting a specific key, the value is going to be an optional `String` type.

The output of this script is _trace_, if the `LOG_LEVEL` is not provided explicitly.

## How to set environment variables?

There are several methods for configuring environment variables, and the approach you take depends on the specific tools you're working with.

Here are some typical scenarios for setting up custom environment variables.


### Setting env vars using the command line

List the desired environment variables before the command when running a Swift package using a terminal window. Key-value pairs should be listed using the `key=value` format, separated by a single space character.

Here's how to define an explicit log level by using the `swift run` command:

```sh
LOG_LEVEL=debug swift run

// output: "debug"
```

The command above makes the `LOG_LEVEL` env variable set to `trace` for the `swift run` process. Traditionally environment variables are uppercased.

The export command extends the availability of an environment variable throughout the shell's entire lifecycle. Here's how to use it:


```sh
echo $LOG_LEVEL // output: ""

export LOG_LEVEL=info

echo $LOG_LEVEL // output: "info"

swift run

// output: "info"
```

The `echo` command is used to display variables in a shell script. Use the $ prefix and the name of the variable to access the value of it.


### Setting env vars using Xcode

In Xcode, you can configure environment variables within the Scheme settings. The interface permits enabling or disabling specific key-value pairs for a particular run.

Here's how to reach the settings:

- Open the project in Xcode.

- Select the "Product" > "Scheme" > "Edit Scheme..." menu item.

Alternatively, click on the Scheme name and select the "Edit Scheme..." menu item:

![Edit Scheme in Xcode](edit-scheme-in-xcode.png)

Inside the popup window:

- Select the "Run" option on the sidebar.

- Select the "Arguments" tab.

![Set env in Xcode](set-env-in-xcode.png)

Finally, add a new entry into the "Environment Variables" section.

Click "Close" to get back to the project and press the "Play" icon to run the app.


### Setting env vars using Visual Studio Code

It is possible to [develop Swift projects with VSCode](https://swiftonserver.com/developing-with-swift-in-visual-studio-code/) using the [official Swift extension](https://www.swift.org/blog/vscode-extension/).

In order to set environment variables in the editor, open the `.vscode/launch.json` file in your workspace or select the "Debug" > "Open Configurations" menu item.

Inside the launch configuration file simply add to a new `env` property, if it's not present, with the desired key-value pairs:

![Set env in VSCode](set-env-in-vscode.png)


Save the launch config and run the project using the "Play" icon inside the "Run and Debug" panel or using the "Run" > "Start Debugging" menu item.


## Using dotenv files

A `.env` file is a text file commonly used to store environment variables for a project. It contains key-value pairs in the form of `KEY=VALUE`, where each line represents a different variable. Developers use libraries or tools to load the variables from the _.env_ file into the application's environment. This allows the application to access these variables as if they were set directly in the system's environment.

NOTE: The _.env_ files should be excluded from git using _.gitignore_.

The _.env_ file provides a flexible and convenient way to manage environment-specific configuration settings in a project while keeping sensitive information secure and separate from the codebase.

Various open-source Swift libraries exist for server-side application developers, providing functionality to parse dotenv files. For instance:

- [thebarndog/swift-dotenv](https://github.com/thebarndog/swift-dotenv)
- [swiftpackages/DotEnv](https://github.com/swiftpackages/DotEnv)
- [clarkgunn/DotEnv/](https://github.com/clarkgunn/DotEnv/)

Most of the modern web frameworks, have excellent support for loading dotenv files. Both [Vapor](https://docs.vapor.codes/basics/environment/?h=environ#env-dotenv) and [Hummingbird](https://hummingbird-project.github.io/hummingbird-docs/1.0/documentation/hummingbirdauth/hbenvironment/dotenv(_:)) have a built-in solution to load and parse environment variables using these files.

## Using the environment in Vapor

Vapor's [Environment API](https://docs.vapor.codes/basics/environment/) enables dynamic configuration of the application:

```swift
import Vapor

// configures your application
public func configure(_ app: Application) async throws {

// 1.
var logger = Logger(label: "vapor-logger")
logger.logLevel = .trace

// 2.
let logLevel = Environment.get("LOG_LEVEL")

// 3.
if let logLevel, let logLevel = Logger.Level(rawValue: logLevel) {
// 4.
logger.logLevel = logLevel
}

try routes(app)
}
```

1. Set up a new _Logger_ instance, set the default log level to _.trace_
2. Get the the raw log level as an optional String using the Environment
3. Cast the log level to a `Logger.Level` enum, if it's a valid input
4. Set the log level based on the environment

Vapor will look for dotenv files in the current working directory. If you're using Xcode, make sure to set the working directory by editing the scheme.

## Using the environment in Hummingbird 2

In Hummingbird, it is possible to use the shared environment or load dotenv files using the static `dotEnv()` method on the [HBEnvironment](https://hummingbird-project.github.io/hummingbird-docs/1.0/documentation/hummingbirdauth/hbenvironment) struct:

```swift
import Hummingbird
import Logging

func buildApplication(
configuration: HBApplicationConfiguration
) async throws -> some HBApplicationProtocol {

var logger = Logger(label: "hummingbird-logger")
logger.logLevel = .trace

let env = HBEnvironment.shared
// let env = try await HBEnvironment.dotEnv()
let logLevel = env.get("LOG_LEVEL")

if let logLevel, let logLevel = Logger.Level(rawValue: logLevel) {
logger.logLevel = logLevel
}

let router = HBRouter()
router.get("/") { _, _ in
return "Hello"
}

let app = HBApplication(
router: router,
configuration: configuration,
logger: logger
)
return app
}
```

If you run the project from Xcode, make sure you set a custom working directory, otherwise the framework won't be able to locate your dotenv file.

## What's next?

Environment variables are crucial for modifying application behavior without code changes, offering flexibility across environments. They're commonly used for feature flags, secrets, and other configuration purposes. In our next article we will discover how to store secrets and API credentials in a secure way.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.