Skip to content

Commit 07062b3

Browse files
authored
Merge pull request #4 from gilesknap/main
Final tweaks from giles
2 parents 5d2026c + ac8e75b commit 07062b3

File tree

18 files changed

+318
-329
lines changed

18 files changed

+318
-329
lines changed

.devcontainer/devcontainer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,7 @@
3434
],
3535
// Mount the parent as /workspaces so we can pip install peers as editable
3636
"workspaceMount": "source=${localWorkspaceFolder}/..,target=/workspaces,type=bind",
37-
"initializeCommand": "mkdir -p ${localEnv:HOME}/.config/devcontainer_rc"
37+
// Create the config folder for the bash-config feature
38+
"initializeCommand": "mkdir -p ${localEnv:HOME}/.config/bash-config",
39+
"remoteUser": "root"
3840
}
Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,47 @@
1-
# Lightweight, Configurable BASH Eternal History
1+
# Lightweight, Configurable BASH Config with Eternal History
22

3-
## Defaults
3+
Intended as a lightweight alternative to common-utils.
44

5-
When this feature is first called, onCreateCommand.sh is created and called in `devcontainer-feature`.
6-
This creates and installs a default bash terminal configuration from `feature_settings_rc` which contains opinionated default BASH terminal settings such as:
7-
* A minimalist, blue bash prompt.
8-
* Eternal, shared history between containers using this feature.
5+
## Installation
96

10-
## Customisation
7+
To use this feature in an individual devcontainer, add the following to your `.devcontainer/devcontainer.json`:
8+
9+
```json
10+
"features": {
11+
"ghcr.io/diamondlightsource/devcontainer-features/bash-config:1": {}
12+
},
13+
"initializeCommand": "mkdir -p ${localEnv:HOME}/.config/bash-config",
14+
```
15+
16+
The initializeCommand is required to create the directory for the bash-config folder in your home folder on the host, the very first time this is executed. Features do not have an InitializeCommand, so the devcontainer.json must do this.
17+
18+
## Global Installation
19+
20+
To use this feature in all devcontainers on your workstation, add the following to User setting.json:
21+
22+
```json
23+
"dev.containers.defaultFeatures": {
24+
"ghcr.io/gilesknap/devcontainer-features/bash-config:1.1.0"
25+
}
26+
```
1127

12-
The user can specify their own terminal preferences in `$CONFIG_STAGING/bashrc`, which defaults to `/devcontainer_staging/bashrc`.
13-
Then the container is rebuilt, if `bashrc` already exists it won't be overwritten, preserving changes. If the container has been built once already, the existing bashrc must be deleted in order for your changes to be applied.
28+
Also, one time only, make sure the host folder for bash-config is created:
1429

30+
```bash
31+
mkdir -p $HOME/.config/bash-config
32+
```
1533

1634

17-
creates staging folder in container
18-
creates onCreateCommand.sh in the staging folder
19-
inputrc and bashrc are also created in the staging folder, containing incremental history searching and user customisations respectively
20-
feature_settings_rc is created in the staging fodler, which contains a PS1 setup and opinionated terminal features
21-
"onCreateCommand" is then exectuted inside the container during finalisation of container setup.
22-
- This copies the contents of feature_settings_rc into devcontainer_rc
23-
- then copies bashrc and inputrc into the container, unless they exist already to prevent overwriting user edits
24-
- then adds root permissions.
25-
A symbolic link to /root/ is created The items in the CONFIG_FOLDER
26-
our bashrc is called by /root/.bashrc
35+
## features
36+
37+
The default, opinionated configuration can be found in `$HOME/.config/bash-config/bash-config-rc` and includes the following:
38+
39+
- Persistent history across all devcontainers that use this feature
40+
- The MS devcontainer bash prompt with git branch and status
41+
- history search with up/down arrows (.inputrc)
42+
- ctrl-left or right arrow for word navigation (.inputrc)
43+
- git autocomplete
44+
45+
## Customisation
46+
47+
Can be customized by editing `$HOME/.config/bash-config/bashrc`
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# bash-config configuration files
2+
3+
## introduction
4+
5+
The files in this folder are copied out of the bash-config feature and
6+
into the users config folder on the host at ~/.config/bash-config
7+
8+
## files
9+
10+
- bashrc: The entry point for the bash-config feature. User editable
11+
- inputrc: The readline configuration file. User editable
12+
- bash-config-rc: The configuration file for the bash-config feature. Not
13+
user editable. Replaced with the latest version on each rebuild of the
14+
developer container.
15+
16+
## Stages
17+
18+
1. At build time all the files in this folder are copied to a staging folder
19+
in the container filesystem.
20+
1. At container runtime the files are copied from the staging folder to the
21+
users config folder on the host.
22+
1. The file onCreateCommand.sh is executed at container creation time in order
23+
to facilitate the above copy.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/bin/bash
2+
3+
# default opinioned bash configuration
4+
5+
# set the prompt
6+
export PS1="\[\033[1;34m\]\W \[\033[0m\]# "
7+
8+
# enable enternal shared history
9+
export HISTCONTROL=ignoreboth:erasedups
10+
export HISTSIZE=-1
11+
export HISTFILESIZE=-1
12+
export SAVEHIST=-1
13+
export HISTFILE=$CONFIG_FOLDER/.bash_eternal_history
14+
15+
# bash theme - partly inspired by https://github.com/ohmyzsh/ohmyzsh/blob/master/themes/robbyrussell.zsh-theme
16+
# from https://github.com/devcontainers/features/blob/main/src/common-utils/scripts/bash_theme_snippet.sh
17+
__bash_prompt() {
18+
local userpart='`export XIT=$? \
19+
&& [ ! -z "${GITHUB_USER:-}" ] && echo -n "\[\033[0;32m\]@${GITHUB_USER:-} " || echo -n "\[\033[0;32m\]\u " \
20+
&& [ "$XIT" -ne "0" ] && echo -n "\[\033[1;31m\]➜" || echo -n "\[\033[0m\]➜"`'
21+
local gitbranch='`\
22+
if [ "$(git config --get devcontainers-theme.hide-status 2>/dev/null)" != 1 ] && [ "$(git config --get codespaces-theme.hide-status 2>/dev/null)" != 1 ]; then \
23+
export BRANCH="$(git --no-optional-locks symbolic-ref --short HEAD 2>/dev/null || git --no-optional-locks rev-parse --short HEAD 2>/dev/null)"; \
24+
if [ "${BRANCH:-}" != "" ]; then \
25+
echo -n "\[\033[0;36m\](\[\033[1;31m\]${BRANCH:-}" \
26+
&& if [ "$(git config --get devcontainers-theme.show-dirty 2>/dev/null)" = 1 ] && \
27+
git --no-optional-locks ls-files --error-unmatch -m --directory --no-empty-directory -o --exclude-standard ":/*" > /dev/null 2>&1; then \
28+
echo -n " \[\033[1;33m\]✗"; \
29+
fi \
30+
&& echo -n "\[\033[0;36m\]) "; \
31+
fi; \
32+
fi`'
33+
local lightblue='\[\033[1;34m\]'
34+
local removecolor='\[\033[0m\]'
35+
PS1="${userpart} ${lightblue}\w ${gitbranch}${removecolor}\$ "
36+
unset -f __bash_prompt
37+
}
38+
__bash_prompt
39+
export PROMPT_DIRTRIM=4
40+
41+
# enable bash completion for git
42+
if [[ -f /usr/share/bash-completion/completions/git ]]; then
43+
source /usr/share/bash-completion/completions/git
44+
elif [[ -f /etc/bash_completion.d/git ]]; then
45+
source /etc/bash_completion.d/git
46+
fi
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
3+
# This bashrc will be source from /root/.bashrc upon launch of every terminal
4+
# in a devcontainer that uses the bash-config feature from
5+
# https://github.com/DiamondLightSource/devcontainer-features
6+
7+
# This file is initialized by bash-config, but you are then free to edit it
8+
9+
# execute default, opinionated settings - delete this line to remove defaults
10+
source $CONFIG_FOLDER/bash-config-rc
11+
12+
if [ ! -f /one-time ]; then
13+
14+
# add your personal one time only (container creation) commands here
15+
16+
touch /one-time
17+
fi
18+
19+
# add your personal settings for every shell below
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Readline configuration for bash shell.
2+
3+
# Incremental history searching with up and down arrows (C-P and C-N for old
4+
# style navigation).
5+
"\e[A": history-search-backward
6+
"\e[B": history-search-forward
7+
8+
# Control left and right for word movement
9+
"\e[5C": forward-word
10+
"\e[5D": backward-word
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/bash
2+
3+
# this script is run once inside the developer container at creation time
4+
5+
# copy in the opinionated default settings from the feature
6+
cp $CONFIG_STAGING/bash-config-rc $CONFIG_FOLDER
7+
8+
# copy in the user editable settings unless they already exist
9+
if [[ ! -f $CONFIG_FOLDER/bashrc ]] ; then
10+
cp $CONFIG_STAGING/bashrc $CONFIG_FOLDER
11+
cp $CONFIG_STAGING/inputrc $CONFIG_FOLDER
12+
fi
13+
14+
# hook in the config to the root account
15+
ln -s $CONFIG_FOLDER/inputrc /root/.inputrc
16+
echo "source $CONFIG_FOLDER/bashrc" >> /root/.bashrc

.devcontainer/features/bash-config/devcontainer-feature.json

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@
22
"name": "Lightweight and configurable BASH eternal history",
33
//ID *must* match parent folder name *exactly*
44
"id": "bash-config",
5-
"version": "1.0.0",
5+
// a default beta version that is replaced by CI when doing tagged releases
6+
"version": "0.0.1-b1",
67
"description": "Lightweight BASH setup with eternal history and PS1 tweaks. Fully configurable.",
7-
"documentationURL": "https://raw.githubusercontent.com/DiamondRC/devcontainer-features/refs/heads/main/.devcontainer/features/bash-config/README.md",
8+
"documentationURL": "https://raw.githubusercontent.com/DiamondLightSource/devcontainer-features/refs/heads/main/.devcontainer/features/bash-config/README.md",
89
"containerEnv": {
9-
"CONFIG_FOLDER": "/devcontainer_rc",
10-
"CONFIG_STAGING": "/devcontainer_staging"
10+
"CONFIG_FOLDER": "/bash-config",
11+
"CONFIG_STAGING": "/bash-config-staging"
1112
},
1213
"mounts": [
1314
{
14-
"source": "${localEnv:HOME}/.config/devcontainer_rc",
15-
"target": "/devcontainer_rc",
15+
"source": "${localEnv:HOME}/.config/bash-config",
16+
"target": "/bash-config",
1617
"type": "bind"
1718
}
1819
],
19-
"onCreateCommand": "bash /devcontainer_staging/onCreateCommand.sh"
20-
}
20+
"onCreateCommand": "bash /bash-config-staging/onCreateCommand.sh"
21+
}
Lines changed: 16 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,24 @@
11
#!/bin/bash
2-
set -e
3-
4-
echo "Activating feature 'terminal-history'"
5-
echo "User: ${_REMOTE_USER} User home: ${_REMOTE_USER_HOME}"
6-
7-
mkdir -p $CONFIG_STAGING
8-
9-
# -------------------------------------------------------------------------------
10-
cat > $CONFIG_STAGING/onCreateCommand.sh \
11-
<< EOF
12-
#!/bin/bash
13-
14-
# copy in the opinionated default settings from the feature
15-
cp $CONFIG_STAGING/feature_settings_rc $CONFIG_FOLDER/feature_settings_rc
16-
17-
# copy in the user editable settings unless they already exist
18-
if [[ ! -f $CONFIG_FOLDER/bashrc ]] ; then
19-
cp $CONFIG_STAGING/bashrc $CONFIG_FOLDER
20-
cp $CONFIG_STAGING/inputrc $CONFIG_FOLDER
21-
fi
222

23-
# hook in the config to the root account
24-
ln -s $CONFIG_FOLDER/inputrc /root/.inputrc
25-
echo "source $CONFIG_FOLDER/bashrc" >> /root/.bashrc
26-
EOF
27-
28-
# -------------------------------------------------------------------------------
29-
cat > $CONFIG_STAGING/inputrc \
30-
<< EOF
31-
# Readline configuration for bash shell.
32-
33-
# Incremental history searching with up and down arrows (C-P and C-N for old
34-
# style navigation).
35-
"\e[A": history-search-backward
36-
"\e[B": history-search-forward
37-
38-
# Control left and right for word movement
39-
"\e[5C": forward-word
40-
"\e[5D": backward-word
41-
EOF
42-
43-
# -------------------------------------------------------------------------------
44-
cat > $CONFIG_STAGING/bashrc \
45-
<< EOF
46-
#!/bin/bash
3+
# abort on error
4+
set -e
475

48-
# execute default opinionated settings - delete this line to remove defaults
49-
source $CONFIG_FOLDER/feature_settings_rc
6+
# discover where this install.sh and its peers have been extracted to
7+
this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
508

51-
# add your personal custom settings below
52-
EOF
539

54-
# -------------------------------------------------------------------------------
55-
cat > $CONFIG_STAGING/feature_settings_rc \
56-
<< EOF
57-
#!/bin/bash
10+
echo "Activating feature 'bash-config'"
11+
echo "User: ${_REMOTE_USER} User home: ${_REMOTE_USER_HOME}"
5812

59-
# default opinioned bash configuration
13+
# This script is run at container build time.
14+
#
15+
# Here we place all the configuration files in a staging area.
16+
#
17+
# Then at container runtime, when the hosts' config folder is mounted in, we
18+
# can copy from the staging area to the mounted host folder
19+
#
20+
# The runtime copy to host folder is performed once only by onCreateCommand.sh
6021

61-
# set the prompt
62-
export PS1="\[\033[1;34m\]\W \[\033[0m\]# "
22+
mkdir -p "$CONFIG_STAGING"
23+
cp -r "$this_dir"/config/* "$CONFIG_STAGING"
6324

64-
# enable enternal shared history
65-
export HISTCONTROL=ignoreboth:erasedups
66-
export HISTSIZE=-1
67-
export HISTFILESIZE=-1
68-
export SAVEHIST=-1
69-
export HISTFILE=$CONFIG_FOLDER/.bash_eternal_history
70-
PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
71-
EOF

.github/workflows/_check.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
on:
2+
workflow_call:
3+
outputs:
4+
branch-pr:
5+
description: The PR number if the branch is in one
6+
value: ${{ jobs.pr.outputs.branch-pr }}
7+
8+
jobs:
9+
pr:
10+
runs-on: "ubuntu-latest"
11+
outputs:
12+
branch-pr: ${{ steps.script.outputs.result }}
13+
steps:
14+
- uses: actions/github-script@v7
15+
id: script
16+
if: github.event_name == 'push'
17+
with:
18+
script: |
19+
const prs = await github.rest.pulls.list({
20+
owner: context.repo.owner,
21+
repo: context.repo.repo,
22+
head: context.repo.owner + ':${{ github.ref_name }}'
23+
})
24+
if (prs.data.length) {
25+
console.log(`::notice ::Skipping CI on branch push as it is already run in PR #${prs.data[0]["number"]}`)
26+
return prs.data[0]["number"]
27+
}

0 commit comments

Comments
 (0)