Skip to content

Commit 4c76cf0

Browse files
authored
feat: rewrite customizing environments (#243)
This previously focused exclusively on shell hooks and used them to run a service. This now shows a user how to leverage the hook, profile, and vars sections to customize their shell environment in an activated environment. There is now a `lint` alias in the environment to make it easier to remember the linter command.
1 parent 2b3d33f commit 4c76cf0

File tree

4 files changed

+141
-106
lines changed

4 files changed

+141
-106
lines changed

.flox/env/manifest.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@
4545
},
4646
"profile": {
4747
"common": "echo \"\"\necho \" ╔═══════════════════════════════════╗\"\necho \" ║ ║\"\necho \" ║ To build a production docs run: ║\"\necho \" ║ > mkdocs build ║\"\necho \" ║ ║\"\necho \" ║ To write docs locally run: ║\"\necho \" ║ > mkdocs serve ║\"\necho \" ║ ║\"\necho \" ╚═══════════════════════════════════╝\"\necho \"\"\n",
48-
"bash": " source \"$(poetry env info --path)/bin/activate\"\n",
49-
"zsh": " source \"$(poetry env info --path)/bin/activate\"\n",
50-
"fish": " source \"$(poetry env info --path)/bin/activate.fish\"\n",
48+
"bash": " source \"$(poetry env info --path)/bin/activate\"\n alias lint=markdownlint-cli2\n",
49+
"zsh": " source \"$(poetry env info --path)/bin/activate\"\n alias lint=markdownlint-cli2\n",
50+
"fish": " source \"$(poetry env info --path)/bin/activate.fish\"\n alias lint markdownlint-cli2\n",
5151
"tcsh": " source \"$(poetry env info --path)/bin/activate.csh\"\n"
5252
},
5353
"options": {

.flox/env/manifest.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,18 @@ echo ""
138138
'''
139139
bash = '''
140140
source "$(poetry env info --path)/bin/activate"
141+
alias lint=markdownlint-cli2
141142
'''
142143
fish = '''
143144
source "$(poetry env info --path)/bin/activate.fish"
145+
alias lint markdownlint-cli2
144146
'''
145147
tcsh = '''
146148
source "$(poetry env info --path)/bin/activate.csh"
147149
'''
148150
zsh = '''
149151
source "$(poetry env info --path)/bin/activate"
152+
alias lint=markdownlint-cli2
150153
'''
151154

152155
# The `[services]` section of the manifest allows you to define services.
Lines changed: 134 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,151 +1,183 @@
11
---
2-
title: Customizing the environment shell hooks
3-
description: Building an enviornment with custom shell hooks.
2+
title: Customizing the shell environment
3+
description: Using setup scripts, aliases, and environment variables to improve your workflows.
44
---
55

6-
# Customizing the environment shell hook
6+
# Customizing the shell environment
77

8-
This guide uses the [environment's][environment_concept]
9-
[shell hooks][hook_concept] to set up a PostgreSQL development database.
8+
Activating a Flox [environment][environment_concept] places you into a subshell.
9+
You likely already have some customizations built into your shell from your shell's configuration (`.bashrc`, `.zshrc`, `config.fish`, etc), but it can be convenient to further customize your shell based on the project that you're working on.
10+
This guide will walk you through leveraging various features of a Flox environment to improve your quality of life when developing a Rust project, but many of the ideas are applicable to other languages as well.
1011

11-
## Create a PostgreSQL environment
12+
## Setup
1213

13-
Say your project has a variable it expects to be set and you need to generate
14-
the value for development.
15-
This is a great use for the environment's **[shell hooks][hook_concept]**.
14+
Let's assume you have a Rust project that you regularly work on.
15+
To do that work you would already have `cargo`, `rustc`, and a few other tools installed.
16+
For more details on what it looks like to develop in Rust with Flox, see the [Rust language guide][rust_guide].
1617

17-
Let's set up a Flox [environment][environment_concept] using the `postgresql_15`
18-
package in your environment:
18+
If you'd like to follow along with a real Flox environment, create an environment via [`flox init`][flox_init] and install the tools as shown below:
1919

20-
``` console
21-
$ flox init --name postgres-example
20+
```bash
21+
$ mkdir mycli
22+
$ cd mycli
23+
$ flox init
24+
$ flox install rustc cargo libiconv
25+
```
2226

23-
✨ Created environment postgres-example (aarch64-darwin)
27+
Then generate a basic "Hello, World" program using `cargo init` inside the environment:
2428

25-
Next:
26-
$ flox search <package> <- Search for a package
27-
$ flox install <package> <- Install a package into an environment
28-
$ flox activate <- Enter the environment
29+
```bash
30+
$ flox activate -- cargo init --bin .
2931
```
3032

31-
``` console
32-
$ flox install postgresql_15
33-
✅ 'postgresql_15' installed to environment postgres-example at /Users/youruser
34-
```
33+
## Vars, hook, or profile?
3534

36-
## Customize the environment's shell hook
35+
When customizing your shell environment you have three basic knobs you can turn:
3736

38-
Let's add some properties PostgreSQL needs to run properly in this
39-
[environment][environment_concept].
37+
- The `[vars]` section
38+
- The `hook.on-activate` script
39+
- The `[profile]` section
4040

41-
``` console
42-
$ flox edit
43-
```
41+
The logic for deciding where a customization should go is application specific, but there are some simple guidelines you can follow.
42+
For a full discussion of what logic to place in which section and why, see the [activation concept page][activation_concept].
43+
Otherwise, try this:
4444

45-
Specifically, let's modify the **[hook section][hook_concept]**
46-
and create a **script**.
47-
All hook scripts inherit variables defined in the `[vars]` section of the manifest,
48-
and environment variables set in the `hook.on-activate` script
49-
are in turn inherited by the `[profile]` scripts that follow.
45+
<!-- markdownlint-disable MD007 -->
46+
- Are you setting an environment variable?
47+
- Is it a constant value?
48+
- If so, set it in the `[vars]` section.
49+
- If not, compute and `export` the variable in the `hook.on-activate` script.
50+
- Are you sourcing a script (like activating a Python virtual environment)?
51+
- If so, do this in the `[profile]` section.
52+
- Are you setting shell aliases?
53+
- If so, set them in the `[profile]` section.
54+
- Are you doing general project setup actions (like creating a directory, etc)?
55+
- If so, do that in the `hook.on-activate` script.
56+
<!-- markdownlint-enable MD007 -->
5057

51-
``` toml title="manifest.toml"
58+
## Adding a directory to PATH
5259

53-
[install]
54-
postgresql_15.pkg-path = "postgresql_15"
60+
It can be convenient to quickly run commands against the development build of a program you're working on.
61+
For instance, if you're working on a command line application you might want to check that the help text is formatted properly by interactively running `mycli -h`.
5562

56-
...
57-
58-
[hook]
59-
on-activate = """
60-
export PGPORT="${PGPORT:-5432}"
61-
62-
export PGUSER=pg-example
63-
export PGPASS=pg-example
64-
export PGDATABASE=example-database
65-
export SESSION_SECRET="$USER-session-secret"
66-
67-
# Postgres environment variables
68-
export PGDATA=$PWD/postgres_data
69-
export PGHOST=$PWD/postgres
70-
export LOG_PATH=$PGHOST/LOG
71-
export DATABASE_URL="postgresql:///$PGDATABASE?host=$PGHOST&port=$PGPORT"
72-
...
63+
In our case, when we build the application `cargo` will place the compiled program in `target/debug`:
7364

7465
```
66+
mycli/
67+
.flox
68+
Cargo.toml
69+
Cargo.lock
70+
src/
71+
main.rs
72+
target/
73+
debug/
74+
mycli
75+
```
76+
77+
If we want to run commands with this newly compiled `mycli`, we can either tell `cargo` to build it (again) and then run it, or we can add `target/debug` to `PATH` so that we can run `mycli` like any other program.
78+
This second option is more convenient, so let's see how you can tell your Flox environment to do that for you automatically.
7579

76-
We can also use the **on-activate** hook
77-
to add initialization logic that runs conditionally.
80+
If we follow the logic listed above, we're wanting to modify an existing environment variable (`PATH`), so we'll do this in the `hook.on-activate` script.
81+
Modify your `hook.on-activate` script to look like this:
7882

79-
``` toml title="manifest.toml"
83+
```toml
8084
[hook]
81-
on-activate = """
85+
on-activate = '''
86+
export PATH="$PWD/target/debug:$PATH"
87+
'''
88+
```
89+
90+
Now if you activate the environment and build `mycli` for the first time, you should be able to run `mycli` without needing to type out the path to it (e.g. `target/debug/mycli`):
91+
92+
```bash
93+
$ flox activate
8294
...
83-
mkdir -p $PGHOST
84-
if [ ! -d $PGDATA ]; then
85-
echo 'Initializing postgresql database...'
86-
initdb $PGDATA --username $PGUSER -A md5 --pwfile=<(echo $PGPASS) --auth=trust
87-
echo "listen_addresses='*'" >> $PGDATA/postgresql.conf
88-
echo "unix_socket_directories='$PGHOST'" >> $PGDATA/postgresql.conf
89-
echo "unix_socket_permissions=0700" >> $PGDATA/postgresql.conf
90-
fi
95+
$ cargo build
9196
...
92-
"""
97+
$ mycli
98+
Hello, World!
9399
```
94100

95-
!!! note "Note"
96-
The `hook.on-activate` script is always run in a `bash` shell.
101+
### Why do I need to exit and re-activate?
97102

98-
**Save and exit your editor**, you should see a confirmation after Flox
99-
validates the environment.
103+
Any time the Flox CLI detects that you've changed a section of the manifest that it can't automatically make take effect, you'll need to exit and reactivate.
104+
For instance, when you install a new package via [`flox install`][flox_install], the CLI is able to make that immediately available to you so there's no need to exit and re-activate.
100105

101-
```
102-
✅ Environment successfully updated.
103-
```
106+
However, editing the `hook.on-activate` script has no effect on the currently activated environment because the `hook.on-activate` script is only run during the activation process (and the same goes for `[profile]`).
107+
Similarly, editing the `[vars]` section has no effect on the currently activated environment because the `hook.on-activate` and `[profile]` scripts may rely on the values of variables in `[vars]`, so for the sake of correctness it makes sense to re-run those scripts.
108+
109+
## Enabling feature flags
104110

105-
## Test the environment
111+
Now let's say that you've worked on `mycli` for a while and developed some features that aren't publicly available, but can be accessed by setting certain feature flags.
112+
A common way to enable or disable feature flags is by environment variables.
113+
If you want to be able to test out those features during development, this sounds like a great thing for Flox to do for you automatically.
106114

107-
You can now [`flox activate`][flox_activate] the environment to see the result
108-
of your hard work!
115+
Let's say that we have feature flags `MYCLI_ENABLE_COLOR` and `MYCLI_TURBO_MODE` and they're enabled when we set them to `"1"`.
109116

117+
Going back to our "vars, hook, or profile" logic, we see that we're trying to set new environment variables with constant values.
118+
This means we'll want to set these variables in the `[vars]` section.
119+
Edit your `[vars]` section to look like this:
120+
121+
```toml
122+
[vars]
123+
MYCLI_ENABLE_COLOR="1"
124+
MYCLI_TURBO_MODE="1"
110125
```
126+
127+
If you're currently in the environment, exit it and activate it again for the changes to take effect, otherwise you can simply activate the environment.
128+
In the activated environment you should now see that these two variables are set:
129+
130+
```bash
111131
$ flox activate
112-
✅ You are now using the environment postgres-example at /Users/youruser.
113-
To stop using this environment, type 'exit'
132+
...
133+
$ echo $MYCLI_TURBO_MODE
134+
1
135+
```
114136

115-
Initializing postgresql database...
116-
The files belonging to this database system will be owned by user "youruser".
117-
This user must also own the server process.
137+
## Adding shell aliases
118138

119-
The database cluster will be initialized with locale "en_US.UTF-8".
120-
The default database encoding has accordingly been set to "UTF8".
121-
The default text search configuration will be set to "english".
139+
Now let's say that you'd like to use `mycli` from anywhere on your system.
140+
Let's also say that you have a `$HOME/bin` directory that you add to `PATH` in your shell's config file.
141+
You might use this as a place to put programs you've compiled yourself that you want to be able to run from anywhere.
142+
We're going to create an alias for your developer environment that will build `mycli` and copy it to this directory so that it's quick and easy to install `mycli` after completing a feature you've been working on.
122143

123-
Data page checksums are disabled.
144+
Going back to our "vars, hook, or profile" logic, we see that we're creating a shell alias.
145+
This means that we'll be adding it to the `[profile]` section.
146+
However, the syntax for defining shell aliases is shell-specific, so we'll need to declare this alias in the subsection that corresponds to our shell.
147+
For this tutorial we'll assume that you're an enlightened [fish shell][fish_shell] user, meaning that we'll edit our `profile.fish` script.
124148

125-
creating directory /Users/youruser/postgres_data ... ok
126-
creating subdirectories ... ok
127-
selecting dynamic shared memory implementation ... posix
128-
selecting default max_connections ... 100
129-
selecting default shared_buffers ... 128MB
130-
selecting default time zone ... America/New_York
131-
creating configuration files ... ok
132-
running bootstrap script ... ok
133-
performing post-bootstrap initialization ... ok
134-
syncing data to disk ... ok
149+
We'll call this alias `install-bin` and it will build `mycli` in "release" mode, i.e. with full optimizations so it runs as fast as possible.
150+
Edit your `[profile]` section to look like this:
135151

136-
Success. You can now start the database server using:
152+
```toml
153+
[profile]
154+
fish = '''
155+
alias install-bin "cargo build --release && cp $PWD/target/release/mycli $HOME/bin/mycli"
156+
'''
157+
```
158+
159+
Again, if you're currently in the environment, exit it.
160+
If you want to test this alias you'll also want to create the `$HOME/bin` directory.
161+
Now if you activate the environment and run `install-bin` you should find a copy of `mycli` in `$HOME/bin`:
137162

138-
pg_ctl -D /Users/youruser/postgres_data -l logfile start
163+
```bash
164+
$ flox activate
165+
...
166+
$ install-bin
167+
...
168+
$ ls $HOME/bin
169+
mycli
139170
```
140171

141172
## Where to next?
142173

143174
- :simple-readme:{ .flox-purple .flox-heart } [Multiple architecture environments][multi-arch-guide]
144175

145-
[flox_edit]: ../reference/command-reference/flox-edit.md
146-
[flox_search]: ../reference/command-reference/flox-search.md
176+
[environment_concept]: ../concepts/environments.md
147177
[flox_activate]: ../reference/command-reference/flox-activate.md
148-
[create_enviornments_guide]: ./creating-environments.md
149178
[multi-arch-guide]: ./multi-arch-environments.md
150-
[environment_concept]: ../concepts/environments.md
151-
[hook_concept]: ../reference/command-reference/manifest.toml.md#hook
179+
[rust_guide]: ../cookbook/languages/rust.md
180+
[flox_init]: ../reference/command-reference/flox-init.md
181+
[activation_concept]: ../concepts/activation.md
182+
[fish_shell]: https://fishshell.com/
183+
[flox_install]: ../reference/command-reference/flox-install.md

mkdocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ nav:
4040
- The default environment: tutorials/default-environment.md
4141
- Sharing environments: tutorials/sharing-environments.md
4242
- Layering multiple environments: tutorials/layering-multiple-environments.md
43-
- Customizing the environment shell hook: tutorials/customizing-environments.md
43+
- Customizing the shell environment: tutorials/customizing-environments.md
4444
- Running Flox in CI/CD: tutorials/ci-cd.md
4545
- Designing cross-platform environments: tutorials/multi-arch-environments.md
4646
- Reusing and combining developer environments: tutorials/composition.md

0 commit comments

Comments
 (0)