Skip to content
This repository was archived by the owner on Jan 12, 2025. It is now read-only.

Commit 5c96e8d

Browse files
authored
✨️ Add new devcontainer feature composer via GitHub releases (#550)
1 parent b9051c6 commit 5c96e8d

File tree

6 files changed

+249
-0
lines changed

6 files changed

+249
-0
lines changed

src/composer/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Composer (via Github Releases)
2+
3+
Composer is an open source dependency management tool for PHP.
4+
5+
## Example DevContainer Usage
6+
7+
```json
8+
"features": {
9+
"ghcr.io/devcontainers-contrib/features/composer:1": {}
10+
}
11+
```
12+
13+
## Options
14+
15+
| Options Id | Description | Type | Default Value |
16+
|-----|-----|-----|-----|
17+
| version | Select the version to install. | string | latest |
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"id": "composer",
3+
"version": "1.0.0",
4+
"name": "Composer (via Github Releases)",
5+
"documentationURL": "http://github.com/devcontainers-contrib/features/tree/main/src/composer",
6+
"description": "Composer is an open source dependency management tool for PHP.",
7+
"options": {
8+
"version": {
9+
"default": "latest",
10+
"description": "Select the version to install.",
11+
"proposals": [
12+
"latest"
13+
],
14+
"type": "string"
15+
}
16+
},
17+
"installsAfter": [
18+
"ghcr.io/devcontainers-contrib/features/gh-release"
19+
]
20+
}

src/composer/install.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash -i
2+
3+
set -e
4+
5+
. ./library_scripts.sh
6+
7+
# nanolayer is a cli utility which keeps container layers as small as possible
8+
# source code: https://github.com/devcontainers-contrib/nanolayer
9+
# `ensure_nanolayer` is a bash function that will find any existing nanolayer installations,
10+
# and if missing - will download a temporary copy that automatically get deleted at the end
11+
# of the script
12+
ensure_nanolayer nanolayer_location "v0.5.4"
13+
14+
$nanolayer_location \
15+
install \
16+
devcontainer-feature \
17+
"ghcr.io/devcontainers-contrib/features/gh-release:1.0.24" \
18+
--option repo='composer/composer' --option binaryNames='composer' --option version="$VERSION"
19+
20+
echo 'Done!'

src/composer/library_scripts.sh

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#!/bin/bash -i
2+
3+
clean_download() {
4+
# The purpose of this function is to download a file with minimal impact on container layer size
5+
# this means if no valid downloader is found (curl or wget) then we install a downloader (currently wget) in a
6+
# temporary manner, and making sure to
7+
# 1. uninstall the downloader at the return of the function
8+
# 2. revert back any changes to the package installer database/cache (for example apt-get lists)
9+
# The above steps will minimize the leftovers being created while installing the downloader
10+
# Supported distros:
11+
# debian/ubuntu/alpine
12+
13+
url=$1
14+
output_location=$2
15+
tempdir=$(mktemp -d)
16+
downloader_installed=""
17+
18+
function _apt_get_install() {
19+
tempdir=$1
20+
21+
# copy current state of apt list - in order to revert back later (minimize contianer layer size)
22+
cp -p -R /var/lib/apt/lists $tempdir
23+
apt-get update -y
24+
apt-get -y install --no-install-recommends wget ca-certificates
25+
}
26+
27+
function _apt_get_cleanup() {
28+
tempdir=$1
29+
30+
echo "removing wget"
31+
apt-get -y purge wget --auto-remove
32+
33+
echo "revert back apt lists"
34+
rm -rf /var/lib/apt/lists/*
35+
rm -r /var/lib/apt/lists && mv $tempdir/lists /var/lib/apt/lists
36+
}
37+
38+
function _apk_install() {
39+
tempdir=$1
40+
# copy current state of apk cache - in order to revert back later (minimize contianer layer size)
41+
cp -p -R /var/cache/apk $tempdir
42+
43+
apk add --no-cache wget
44+
}
45+
46+
function _apk_cleanup() {
47+
tempdir=$1
48+
49+
echo "removing wget"
50+
apk del wget
51+
}
52+
53+
# try to use either wget or curl if one of them already installer
54+
if type curl >/dev/null 2>&1; then
55+
downloader=curl
56+
elif type wget >/dev/null 2>&1; then
57+
downloader=wget
58+
else
59+
downloader=""
60+
fi
61+
62+
# in case none of them is installed, install wget temporarly
63+
if [ -z $downloader ] ; then
64+
if [ -x "/usr/bin/apt-get" ] ; then
65+
_apt_get_install $tempdir
66+
elif [ -x "/sbin/apk" ] ; then
67+
_apk_install $tempdir
68+
else
69+
echo "distro not supported"
70+
exit 1
71+
fi
72+
downloader="wget"
73+
downloader_installed="true"
74+
fi
75+
76+
if [ $downloader = "wget" ] ; then
77+
wget -q $url -O $output_location
78+
else
79+
curl -sfL $url -o $output_location
80+
fi
81+
82+
# NOTE: the cleanup procedure was not implemented using `trap X RETURN` only because
83+
# alpine lack bash, and RETURN is not a valid signal under sh shell
84+
if ! [ -z $downloader_installed ] ; then
85+
if [ -x "/usr/bin/apt-get" ] ; then
86+
_apt_get_cleanup $tempdir
87+
elif [ -x "/sbin/apk" ] ; then
88+
_apk_cleanup $tempdir
89+
else
90+
echo "distro not supported"
91+
exit 1
92+
fi
93+
fi
94+
95+
}
96+
97+
ensure_nanolayer() {
98+
# Ensure existance of the nanolayer cli program
99+
local variable_name=$1
100+
101+
local required_version=$2
102+
# normalize version
103+
if ! [[ $required_version == v* ]]; then
104+
required_version=v$required_version
105+
fi
106+
107+
local nanolayer_location=""
108+
109+
# If possible - try to use an already installed nanolayer
110+
if [[ -z "${NANOLAYER_FORCE_CLI_INSTALLATION}" ]]; then
111+
if [[ -z "${NANOLAYER_CLI_LOCATION}" ]]; then
112+
if type nanolayer >/dev/null 2>&1; then
113+
echo "Found a pre-existing nanolayer in PATH"
114+
nanolayer_location=nanolayer
115+
fi
116+
elif [ -f "${NANOLAYER_CLI_LOCATION}" ] && [ -x "${NANOLAYER_CLI_LOCATION}" ] ; then
117+
nanolayer_location=${NANOLAYER_CLI_LOCATION}
118+
echo "Found a pre-existing nanolayer which were given in env variable: $nanolayer_location"
119+
fi
120+
121+
# make sure its of the required version
122+
if ! [[ -z "${nanolayer_location}" ]]; then
123+
local current_version
124+
current_version=$($nanolayer_location --version)
125+
if ! [[ $current_version == v* ]]; then
126+
current_version=v$current_version
127+
fi
128+
129+
if ! [ $current_version == $required_version ]; then
130+
echo "skipping usage of pre-existing nanolayer. (required version $required_version does not match existing version $current_version)"
131+
nanolayer_location=""
132+
fi
133+
fi
134+
135+
fi
136+
137+
# If not previuse installation found, download it temporarly and delete at the end of the script
138+
if [[ -z "${nanolayer_location}" ]]; then
139+
140+
if [ "$(uname -sm)" == "Linux x86_64" ] || [ "$(uname -sm)" == "Linux aarch64" ]; then
141+
tmp_dir=$(mktemp -d -t nanolayer-XXXXXXXXXX)
142+
143+
clean_up () {
144+
ARG=$?
145+
rm -rf $tmp_dir
146+
exit $ARG
147+
}
148+
trap clean_up EXIT
149+
150+
151+
if [ -x "/sbin/apk" ] ; then
152+
clib_type=musl
153+
else
154+
clib_type=gnu
155+
fi
156+
157+
tar_filename=nanolayer-"$(uname -m)"-unknown-linux-$clib_type.tgz
158+
159+
# clean download will minimize leftover in case a downloaderlike wget or curl need to be installed
160+
clean_download https://github.com/devcontainers-contrib/cli/releases/download/$required_version/$tar_filename $tmp_dir/$tar_filename
161+
162+
tar xfzv $tmp_dir/$tar_filename -C "$tmp_dir"
163+
chmod a+x $tmp_dir/nanolayer
164+
nanolayer_location=$tmp_dir/nanolayer
165+
166+
167+
else
168+
echo "No binaries compiled for non-x86-linux architectures yet: $(uname -m)"
169+
exit 1
170+
fi
171+
fi
172+
173+
# Expose outside the resolved location
174+
declare -g ${variable_name}=$nanolayer_location
175+
}

test/composer/scenarios.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"test_defaults_debian": {
3+
"image": "mcr.microsoft.com/devcontainers/php",
4+
"features": {
5+
"composer": {}
6+
}
7+
}
8+
}

test/composer/test_defaults_debian.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash -i
2+
3+
set -e
4+
5+
source dev-container-features-test-lib
6+
7+
check "composer --version" composer --version
8+
9+
reportResults

0 commit comments

Comments
 (0)