mirror of
https://github.com/directus/directus.git
synced 2026-04-03 03:00:39 -04:00
Build improvements (#6759)
* test * ci improvements * fix image names * improve docs * Update .github/workflows/release.yml Co-authored-by: Pascal Jufer <paescuj@users.noreply.github.com> * Update docker/pack.js Co-authored-by: Pascal Jufer <paescuj@users.noreply.github.com> * improvements proposed by @paescuj * improve Dockerfile comment * fix .PHONY * rm tarballs before building final image Co-authored-by: Pascal Jufer <paescuj@users.noreply.github.com>
This commit is contained in:
15
.github/actions/build-images/Dockerfile
vendored
15
.github/actions/build-images/Dockerfile
vendored
@@ -1,15 +0,0 @@
|
||||
FROM docker:stable
|
||||
|
||||
RUN \
|
||||
apk update && \
|
||||
apk upgrade && \
|
||||
apk add bash
|
||||
|
||||
COPY ./rootfs/ /
|
||||
|
||||
RUN \
|
||||
chmod +x /usr/bin/lib/argsf && \
|
||||
chmod +x /usr/bin/entrypoint && \
|
||||
chmod +x /usr/bin/semver
|
||||
|
||||
ENTRYPOINT ["entrypoint"]
|
||||
47
.github/actions/build-images/action.yml
vendored
47
.github/actions/build-images/action.yml
vendored
@@ -1,47 +0,0 @@
|
||||
name: "Build and publish Directus images"
|
||||
description: "GitHub Action to publish Directus container images."
|
||||
branding:
|
||||
icon: archive
|
||||
color: gray-dark
|
||||
inputs:
|
||||
repository:
|
||||
description: "Repository name"
|
||||
required: true
|
||||
registry:
|
||||
description: "Registry"
|
||||
required: true
|
||||
username:
|
||||
description: "Registry user"
|
||||
required: true
|
||||
password:
|
||||
description: "Registry password"
|
||||
required: true
|
||||
version:
|
||||
description: "Version"
|
||||
required: true
|
||||
push:
|
||||
description: "Push"
|
||||
required: false
|
||||
default: "false"
|
||||
latest:
|
||||
description: "Latest"
|
||||
required: false
|
||||
default: "false"
|
||||
runs:
|
||||
using: "docker"
|
||||
image: "Dockerfile"
|
||||
args:
|
||||
- --registry
|
||||
- ${{ inputs.registry }}
|
||||
- --repository
|
||||
- ${{ inputs.repository }}
|
||||
- --username
|
||||
- ${{ inputs.username }}
|
||||
- --password
|
||||
- ${{ inputs.password }}
|
||||
- --version
|
||||
- ${{ inputs.version }}
|
||||
- --push
|
||||
- ${{ inputs.push }}
|
||||
- --latest
|
||||
- ${{ inputs.latest }}
|
||||
@@ -1,13 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
tab_width = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
bootstrap() {
|
||||
local warn=false
|
||||
|
||||
if [[ -z $KEY && -z $KEY_FILE ]]; then
|
||||
KEY=$(uuidgen)
|
||||
export KEY
|
||||
warn=true
|
||||
fi
|
||||
|
||||
if [[ -z $SECRET && -z $SECRET_FILE ]]; then
|
||||
SECRET=$(node -e 'console.log(require("nanoid").nanoid(32))')
|
||||
export SECRET
|
||||
warn=true
|
||||
fi
|
||||
|
||||
if [[ $warn == 'true' ]]; then
|
||||
print --level=warn --stdin <<WARN
|
||||
>
|
||||
> WARNING!
|
||||
>
|
||||
> The KEY and SECRET environment variables are not set. Some
|
||||
> temporary variables were generated to fill the gap, but in
|
||||
> production this is going to cause problems.
|
||||
>
|
||||
> Reference:
|
||||
> https://docs.directus.io/reference/environment-variables.html
|
||||
>
|
||||
>
|
||||
WARN
|
||||
fi
|
||||
|
||||
# Create folder if using sqlite and file doesn't exist
|
||||
if [[ $DB_CLIENT == 'sqlite3' ]]; then
|
||||
if [[ -z $DB_FILENAME ]]; then
|
||||
print --level=error "Missing DB_FILENAME environment variable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f $DB_FILENAME ]]; then
|
||||
mkdir -p "$(dirname "$DB_FILENAME")"
|
||||
fi
|
||||
fi
|
||||
|
||||
npx directus bootstrap
|
||||
}
|
||||
|
||||
command=''
|
||||
if [[ $# -eq 0 ]]; then
|
||||
command="start"
|
||||
elif [[ $1 == 'bash' || $1 == 'shell' ]]; then
|
||||
shift
|
||||
exec bash "$@"
|
||||
elif [[ $1 == 'command' ]]; then
|
||||
shift
|
||||
exec "$@"
|
||||
else
|
||||
command="$1"
|
||||
shift
|
||||
fi
|
||||
|
||||
bootstrap
|
||||
exec npx directus "$command" "$@"
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Workarounds?
|
||||
process.env.NODE_PATH = "/usr/local/lib/node_modules";
|
||||
require("module").Module._initPaths();
|
||||
|
||||
/**
|
||||
* Read lines from stdin
|
||||
*/
|
||||
async function readlines() {
|
||||
const chunks = [];
|
||||
for await (const chunk of process.stdin) {
|
||||
chunks.push(chunk);
|
||||
}
|
||||
|
||||
const lines = chunks.join("").split("\n");
|
||||
lines.pop();
|
||||
return lines;
|
||||
}
|
||||
|
||||
(async function () {
|
||||
// Logger
|
||||
const yargs = require("yargs");
|
||||
const logger = require("pino")({
|
||||
prettyPrint: process.env.LOG_STYLE !== "raw",
|
||||
prettifier: require("pino-colada"),
|
||||
level: process.env.LOG_LEVEL || "info",
|
||||
});
|
||||
|
||||
function write(...message) {
|
||||
if (level in logger) {
|
||||
logger[level](...message);
|
||||
} else {
|
||||
logger.info(...message);
|
||||
}
|
||||
}
|
||||
|
||||
const args = yargs.argv;
|
||||
const level = args.level || "info";
|
||||
const stdin = args.stdin || false;
|
||||
|
||||
if (stdin) {
|
||||
const lines = await readlines();
|
||||
lines.forEach((line) => write(line));
|
||||
} else {
|
||||
write(...args._);
|
||||
}
|
||||
})();
|
||||
@@ -1,138 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
root=$(dirname ${0})
|
||||
source ${root}/lib/argsf
|
||||
|
||||
#
|
||||
# Makes a set of tags
|
||||
#
|
||||
function make_tags() {
|
||||
local prefix=""
|
||||
local version=${1}
|
||||
|
||||
semver get major ${version} > /dev/null 2>&1
|
||||
if [ "$?" != "0" ]; then
|
||||
echo "${version}"
|
||||
else
|
||||
if [ "${version:0:1}" == "v" ]; then
|
||||
prefix="v"
|
||||
fi
|
||||
|
||||
major="$(semver get major ${version})"
|
||||
minor="${major}.$(semver get minor ${version})"
|
||||
patch="${minor}.$(semver get patch ${version})"
|
||||
|
||||
prerel="$(semver get prerel ${version})"
|
||||
if [ "${prerel}" == "" ]; then
|
||||
is_prerel=false
|
||||
else
|
||||
is_prerel=true
|
||||
fi
|
||||
|
||||
build="$(semver get build ${version})"
|
||||
if [ "${build}" == "" ]; then
|
||||
is_build=false
|
||||
else
|
||||
is_build=true
|
||||
fi
|
||||
|
||||
if [ "${is_prerel}" == "true" ]; then
|
||||
echo "${prefix}${major}-${prerel}"
|
||||
echo "${prefix}${minor}-${prerel}"
|
||||
echo "${prefix}${patch}-${prerel}"
|
||||
if [ "${is_build}" == "true" ]; then
|
||||
echo "${prefix}${major}-${prerel}-${build}"
|
||||
fi
|
||||
else
|
||||
echo "${prefix}${major}"
|
||||
echo "${prefix}${minor}"
|
||||
echo "${prefix}${patch}"
|
||||
if [ "${is_build}" == "true" ]; then
|
||||
echo "${prefix}${patch}-${build}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Build script
|
||||
#
|
||||
function main() {
|
||||
username=$(argument username)
|
||||
password=$(argument password)
|
||||
|
||||
push=$(argument push "false")
|
||||
latest=$(argument latest "false")
|
||||
|
||||
registry=$(argument registry "")
|
||||
registry=$(echo "${registry}" | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
repository=$(argument repository "directus/directus")
|
||||
repository=$(echo "${repository}" | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
version=$(argument version "")
|
||||
context=$(argument context ".")
|
||||
|
||||
image="${repository}"
|
||||
if [ "${registry}" != "" ]; then
|
||||
image="${registry}/${image}"
|
||||
fi
|
||||
|
||||
# Normalize tag
|
||||
if [ "${version}" == "" ]; then
|
||||
version=${GITHUB_REF##*/}
|
||||
else
|
||||
version=${version##*/}
|
||||
fi
|
||||
|
||||
if [ "${version}" == "" ]; then
|
||||
version=$(echo ${GITHUB_SHA:-"000000000000"} | cut -c1-12)
|
||||
fi
|
||||
|
||||
tags=$(make_tags ${version})
|
||||
echo "Tags = ${tags}"
|
||||
|
||||
# build image
|
||||
docker build \
|
||||
-t directus:main \
|
||||
--build-arg VERSION=${version} \
|
||||
--build-arg REPOSITORY=${repository} \
|
||||
/directus/images/main
|
||||
|
||||
# login into registry
|
||||
docker login -u "${username}" -p "${password}" "${registry}"
|
||||
|
||||
# Push latest
|
||||
# TODO: check if it's really the latest
|
||||
if [ "${latest}" == "true" ]; then
|
||||
fqin="${image}:latest"
|
||||
echo "Tagging ${fqin}"
|
||||
docker tag directus:main ${fqin}
|
||||
if [ "${push}" == "true" ]; then
|
||||
echo "Pushing tag ${fqin}"
|
||||
docker push "${fqin}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Push tags
|
||||
for tag in $tags
|
||||
do
|
||||
tag=$(echo "${tag}" | tr '[:upper:]' '[:lower:]')
|
||||
fqin="${image}:${tag}"
|
||||
echo "Tagging ${fqin}"
|
||||
docker tag directus:main "${fqin}"
|
||||
if [ "${push}" == "true" ]; then
|
||||
echo "Pushing tag ${fqin}"
|
||||
docker push "${fqin}"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Finished."
|
||||
|
||||
exit $?
|
||||
}
|
||||
|
||||
main
|
||||
exit $?
|
||||
@@ -1,98 +0,0 @@
|
||||
#
|
||||
# Arguments and Flags (argsf)
|
||||
# This is meant to work with bash shell
|
||||
# To use, source this file into your bash scripts
|
||||
#
|
||||
# Implemented by João Biondo <wolfulus@gmail.com>
|
||||
# https://github.com/WoLfulus/argsf
|
||||
#
|
||||
|
||||
declare _ARGCOUNT=$#
|
||||
declare _ARGDATA=("$@")
|
||||
declare -A _ARGMAP
|
||||
declare -A _FLAGMAP
|
||||
|
||||
for ((_arg_index_key=1;_arg_index_key<=$#;_arg_index_key++))
|
||||
do
|
||||
_arg_index_value=$(expr $_arg_index_key + 1)
|
||||
_arg_key=${!_arg_index_key}
|
||||
_arg_value=${!_arg_index_value}
|
||||
if [[ $_arg_key == *"--"* ]]; then
|
||||
if [[ $_arg_key == *" "* ]]; then
|
||||
continue
|
||||
fi
|
||||
_arg_name="${_arg_key:2}"
|
||||
_FLAGMAP[${_arg_name}]=1
|
||||
if [[ $_arg_value != *"--"* ]] || [[ $_arg_value == *" "* ]] ; then
|
||||
_ARGMAP[${_arg_name}]="$_arg_value"
|
||||
else
|
||||
_ARGMAP[${_arg_name}]=""
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
function _argument() {
|
||||
if test "${_ARGMAP[${ARG_NAME}]+isset}" ; then
|
||||
echo ${_ARGMAP[${ARG_NAME}]}
|
||||
else
|
||||
if [ ${ARG_DEFAULT} -eq 0 ]; then
|
||||
echo "Error: required argument '--${ARG_NAME}' not specified" 1>&2
|
||||
exit 1
|
||||
else
|
||||
echo ${ARG_DEFAULT_VALUE}
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function argument() {
|
||||
if [ $# -eq 1 ]; then
|
||||
ARG_NAME="$1" ARG_DEFAULT=0 ARG_DEFAULT_VALUE= _argument "${_ARGUMENT_DATA}"
|
||||
elif [ $# -eq 2 ]; then
|
||||
ARG_NAME="$1" ARG_DEFAULT=1 ARG_DEFAULT_VALUE="$2" _argument "${_ARGUMENT_DATA}"
|
||||
else
|
||||
echo "argument: invalid number of arguments" 1>&2
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
function flage() {
|
||||
if [ $# -eq 1 ]; then
|
||||
if [[ ${_FLAGMAP[$1]} ]] ; then
|
||||
echo "true"
|
||||
return 0
|
||||
elif [[ ${_FLAGMAP[no-$1]} ]] ; then
|
||||
echo "false"
|
||||
return 0
|
||||
else
|
||||
echo "true"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
echo "flag: invalid number of arguments" 1>&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function flagd() {
|
||||
if [ $# -eq 1 ]; then
|
||||
if [[ ${_FLAGMAP[$1]} ]] ; then
|
||||
echo "true"
|
||||
return 0
|
||||
elif [[ ${_FLAGMAP[no-$1]} ]] ; then
|
||||
echo "false"
|
||||
return 0
|
||||
else
|
||||
echo "false"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
echo "flag: invalid number of arguments" 1>&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function flag() {
|
||||
flagd $1
|
||||
return $?
|
||||
}
|
||||
284
.github/actions/build-images/rootfs/usr/bin/semver
vendored
284
.github/actions/build-images/rootfs/usr/bin/semver
vendored
@@ -1,284 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#
|
||||
# Copyright (c) 2014-2015 François Saint-Jacques <fsaintjacques@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation; either version 3, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
set -o errexit -o nounset -o pipefail
|
||||
|
||||
NAT='0|[1-9][0-9]*'
|
||||
ALPHANUM='[0-9]*[A-Za-z-][0-9A-Za-z-]*'
|
||||
IDENT="$NAT|$ALPHANUM"
|
||||
FIELD='[0-9A-Za-z-]+'
|
||||
|
||||
SEMVER_REGEX="\
|
||||
^[vV]?\
|
||||
($NAT)\\.($NAT)\\.($NAT)\
|
||||
(\\-(${IDENT})(\\.(${IDENT}))*)?\
|
||||
(\\+${FIELD}(\\.${FIELD})*)?$"
|
||||
|
||||
PROG=semver
|
||||
PROG_VERSION="3.0.0"
|
||||
|
||||
USAGE="\
|
||||
Usage:
|
||||
$PROG bump (major|minor|patch|release|prerel <prerel>|build <build>) <version>
|
||||
$PROG compare <version> <other_version>
|
||||
$PROG get (major|minor|patch|release|prerel|build) <version>
|
||||
$PROG --help
|
||||
$PROG --version
|
||||
Arguments:
|
||||
<version> A version must match the following regular expression:
|
||||
\"${SEMVER_REGEX}\"
|
||||
In English:
|
||||
-- The version must match X.Y.Z[-PRERELEASE][+BUILD]
|
||||
where X, Y and Z are non-negative integers.
|
||||
-- PRERELEASE is a dot separated sequence of non-negative integers and/or
|
||||
identifiers composed of alphanumeric characters and hyphens (with
|
||||
at least one non-digit). Numeric identifiers must not have leading
|
||||
zeros. A hyphen (\"-\") introduces this optional part.
|
||||
-- BUILD is a dot separated sequence of identifiers composed of alphanumeric
|
||||
characters and hyphens. A plus (\"+\") introduces this optional part.
|
||||
<other_version> See <version> definition.
|
||||
<prerel> A string as defined by PRERELEASE above.
|
||||
<build> A string as defined by BUILD above.
|
||||
Options:
|
||||
-v, --version Print the version of this tool.
|
||||
-h, --help Print this help message.
|
||||
Commands:
|
||||
bump Bump by one of major, minor, patch; zeroing or removing
|
||||
subsequent parts. \"bump prerel\" sets the PRERELEASE part and
|
||||
removes any BUILD part. \"bump build\" sets the BUILD part.
|
||||
\"bump release\" removes any PRERELEASE or BUILD parts.
|
||||
The bumped version is written to stdout.
|
||||
compare Compare <version> with <other_version>, output to stdout the
|
||||
following values: -1 if <other_version> is newer, 0 if equal, 1 if
|
||||
older. The BUILD part is not used in comparisons.
|
||||
get Extract given part of <version>, where part is one of major, minor,
|
||||
patch, prerel, build, or release.
|
||||
See also:
|
||||
https://semver.org -- Semantic Versioning 2.0.0"
|
||||
|
||||
function error {
|
||||
echo -e "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
function usage-help {
|
||||
error "$USAGE"
|
||||
}
|
||||
|
||||
function usage-version {
|
||||
echo -e "${PROG}: $PROG_VERSION"
|
||||
exit 0
|
||||
}
|
||||
|
||||
function validate-version {
|
||||
local version=$1
|
||||
if [[ "$version" =~ $SEMVER_REGEX ]]; then
|
||||
# if a second argument is passed, store the result in var named by $2
|
||||
if [ "$#" -eq "2" ]; then
|
||||
local major=${BASH_REMATCH[1]}
|
||||
local minor=${BASH_REMATCH[2]}
|
||||
local patch=${BASH_REMATCH[3]}
|
||||
local prere=${BASH_REMATCH[4]}
|
||||
local build=${BASH_REMATCH[8]}
|
||||
eval "$2=(\"$major\" \"$minor\" \"$patch\" \"$prere\" \"$build\")"
|
||||
else
|
||||
echo "$version"
|
||||
fi
|
||||
else
|
||||
error "version $version does not match the semver scheme 'X.Y.Z(-PRERELEASE)(+BUILD)'. See help for more information."
|
||||
fi
|
||||
}
|
||||
|
||||
function is-nat {
|
||||
[[ "$1" =~ ^($NAT)$ ]]
|
||||
}
|
||||
|
||||
function is-null {
|
||||
[ -z "$1" ]
|
||||
}
|
||||
|
||||
function order-nat {
|
||||
[ "$1" -lt "$2" ] && { echo -1 ; return ; }
|
||||
[ "$1" -gt "$2" ] && { echo 1 ; return ; }
|
||||
echo 0
|
||||
}
|
||||
|
||||
function order-string {
|
||||
[[ $1 < $2 ]] && { echo -1 ; return ; }
|
||||
[[ $1 > $2 ]] && { echo 1 ; return ; }
|
||||
echo 0
|
||||
}
|
||||
|
||||
# given two (named) arrays containing NAT and/or ALPHANUM fields, compare them
|
||||
# one by one according to semver 2.0.0 spec. Return -1, 0, 1 if left array ($1)
|
||||
# is less-than, equal, or greater-than the right array ($2). The longer array
|
||||
# is considered greater-than the shorter if the shorter is a prefix of the longer.
|
||||
#
|
||||
function compare-fields {
|
||||
local l="$1[@]"
|
||||
local r="$2[@]"
|
||||
local leftfield=( "${!l}" )
|
||||
local rightfield=( "${!r}" )
|
||||
local left
|
||||
local right
|
||||
|
||||
local i=$(( -1 ))
|
||||
local order=$(( 0 ))
|
||||
|
||||
while true
|
||||
do
|
||||
[ $order -ne 0 ] && { echo $order ; return ; }
|
||||
|
||||
: $(( i++ ))
|
||||
left="${leftfield[$i]}"
|
||||
right="${rightfield[$i]}"
|
||||
|
||||
is-null "$left" && is-null "$right" && { echo 0 ; return ; }
|
||||
is-null "$left" && { echo -1 ; return ; }
|
||||
is-null "$right" && { echo 1 ; return ; }
|
||||
|
||||
is-nat "$left" && is-nat "$right" && { order=$(order-nat "$left" "$right") ; continue ; }
|
||||
is-nat "$left" && { echo -1 ; return ; }
|
||||
is-nat "$right" && { echo 1 ; return ; }
|
||||
{ order=$(order-string "$left" "$right") ; continue ; }
|
||||
done
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2206 # checked by "validate"; ok to expand prerel id's into array
|
||||
function compare-version {
|
||||
local order
|
||||
validate-version "$1" V
|
||||
validate-version "$2" V_
|
||||
|
||||
# compare major, minor, patch
|
||||
|
||||
local left=( "${V[0]}" "${V[1]}" "${V[2]}" )
|
||||
local right=( "${V_[0]}" "${V_[1]}" "${V_[2]}" )
|
||||
|
||||
order=$(compare-fields left right)
|
||||
[ "$order" -ne 0 ] && { echo "$order" ; return ; }
|
||||
|
||||
# compare pre-release ids when M.m.p are equal
|
||||
|
||||
local prerel="${V[3]:1}"
|
||||
local prerel_="${V_[3]:1}"
|
||||
local left=( ${prerel//./ } )
|
||||
local right=( ${prerel_//./ } )
|
||||
|
||||
# if left and right have no pre-release part, then left equals right
|
||||
# if only one of left/right has pre-release part, that one is less than simple M.m.p
|
||||
|
||||
[ -z "$prerel" ] && [ -z "$prerel_" ] && { echo 0 ; return ; }
|
||||
[ -z "$prerel" ] && { echo 1 ; return ; }
|
||||
[ -z "$prerel_" ] && { echo -1 ; return ; }
|
||||
|
||||
# otherwise, compare the pre-release id's
|
||||
|
||||
compare-fields left right
|
||||
}
|
||||
|
||||
function command-bump {
|
||||
local new; local version; local sub_version; local command;
|
||||
|
||||
case $# in
|
||||
2) case $1 in
|
||||
major|minor|patch|release) command=$1; version=$2;;
|
||||
*) usage-help;;
|
||||
esac ;;
|
||||
3) case $1 in
|
||||
prerel|build) command=$1; sub_version=$2 version=$3 ;;
|
||||
*) usage-help;;
|
||||
esac ;;
|
||||
*) usage-help;;
|
||||
esac
|
||||
|
||||
validate-version "$version" parts
|
||||
# shellcheck disable=SC2154
|
||||
local major="${parts[0]}"
|
||||
local minor="${parts[1]}"
|
||||
local patch="${parts[2]}"
|
||||
local prere="${parts[3]}"
|
||||
local build="${parts[4]}"
|
||||
|
||||
case "$command" in
|
||||
major) new="$((major + 1)).0.0";;
|
||||
minor) new="${major}.$((minor + 1)).0";;
|
||||
patch) new="${major}.${minor}.$((patch + 1))";;
|
||||
release) new="${major}.${minor}.${patch}";;
|
||||
prerel) new=$(validate-version "${major}.${minor}.${patch}-${sub_version}");;
|
||||
build) new=$(validate-version "${major}.${minor}.${patch}${prere}+${sub_version}");;
|
||||
*) usage-help ;;
|
||||
esac
|
||||
|
||||
echo "$new"
|
||||
exit 0
|
||||
}
|
||||
|
||||
function command-compare {
|
||||
local v; local v_;
|
||||
|
||||
case $# in
|
||||
2) v=$(validate-version "$1"); v_=$(validate-version "$2") ;;
|
||||
*) usage-help ;;
|
||||
esac
|
||||
|
||||
set +u # need unset array element to evaluate to null
|
||||
compare-version "$v" "$v_"
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
function command-get {
|
||||
local part version
|
||||
|
||||
if [[ "$#" -ne "2" ]] || [[ -z "$1" ]] || [[ -z "$2" ]]; then
|
||||
usage-help
|
||||
exit 0
|
||||
fi
|
||||
|
||||
part="$1"
|
||||
version="$2"
|
||||
|
||||
validate-version "$version" parts
|
||||
local major="${parts[0]}"
|
||||
local minor="${parts[1]}"
|
||||
local patch="${parts[2]}"
|
||||
local prerel="${parts[3]:1}"
|
||||
local build="${parts[4]:1}"
|
||||
local release="${major}.${minor}.${patch}"
|
||||
|
||||
case "$part" in
|
||||
major|minor|patch|release|prerel|build) echo "${!part}" ;;
|
||||
*) usage-help ;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
case $# in
|
||||
0) echo "Unknown command: $*"; usage-help;;
|
||||
esac
|
||||
|
||||
case $1 in
|
||||
--help|-h) echo -e "$USAGE"; exit 0;;
|
||||
--version|-v) usage-version ;;
|
||||
bump) shift; command-bump "$@";;
|
||||
get) shift; command-get "$@";;
|
||||
compare) shift; command-compare "$@";;
|
||||
*) echo "Unknown arguments: $*"; usage-help;;
|
||||
esac
|
||||
39
.github/workflows/build-images.yml
vendored
39
.github/workflows/build-images.yml
vendored
@@ -1,39 +0,0 @@
|
||||
name: build-images
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Sleep for 30 seconds
|
||||
uses: jakejarvis/wait-action@master
|
||||
with:
|
||||
time: '30s'
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build GitHub Container Registry
|
||||
uses: ./.github/actions/build-images
|
||||
with:
|
||||
registry: "ghcr.io"
|
||||
repository: "${{ github.repository }}"
|
||||
username: "${{ secrets.REGISTRY_USERNAME }}"
|
||||
password: "${{ secrets.REGISTRY_PASSWORD }}"
|
||||
version: "${{ github.ref }}"
|
||||
latest: "true"
|
||||
push: "true"
|
||||
|
||||
- name: Build Docker Hub
|
||||
uses: ./.github/actions/build-images
|
||||
with:
|
||||
registry: "docker.io"
|
||||
repository: "${{ github.repository }}"
|
||||
username: "${{ secrets.DOCKERHUB_USERNAME }}"
|
||||
password: "${{ secrets.DOCKERHUB_PASSWORD }}"
|
||||
version: "${{ github.ref }}"
|
||||
latest: "true"
|
||||
push: "true"
|
||||
24
.github/workflows/create-release.yml
vendored
24
.github/workflows/create-release.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: create-release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPOSITORY_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: ${{ github.ref }}
|
||||
body: |
|
||||
Directus ${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
118
.github/workflows/release.yml
vendored
Normal file
118
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
name: build-images
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
env:
|
||||
GHCR_IMAGE: ghcr.io/${{ github.repository }}
|
||||
DOCKERHUB_IMAGE: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
create-release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: ${{ github.ref }}
|
||||
body: |
|
||||
Directus ${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16.x'
|
||||
|
||||
- uses: c-hive/gha-npm-cache@v1
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: node docker/pack
|
||||
|
||||
- name: Cache build artifacts
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: '**/dist'
|
||||
key: build-artifacts-${{ github.sha }}
|
||||
|
||||
publish-npm:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Check NPM_TOKEN secret
|
||||
if: secrets.NPM_TOKEN == null || secrets.NPM_TOKEN == ''
|
||||
run: exit 1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Restore build artifacts
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: '**/dist'
|
||||
key: build-artifacts-${{ github.sha }}
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16.x'
|
||||
|
||||
- run: npx lerna publish --force-publish --exact from-git --yes
|
||||
|
||||
build-images:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Restore build artifacts
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: '**/dist'
|
||||
key: build-artifacts-${{ github.sha }}
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
images: |
|
||||
${{ env.DOCKERHUB_IMAGE }}
|
||||
${{ env.GHCR_IMAGE }}
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
if: ${{ env.DOCKERHUB_IMAGE }}
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v1
|
||||
if: ${{ env.GHCR_IMAGE }}
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: './docker/Dockerfile'
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
push: true
|
||||
@@ -1,21 +1,9 @@
|
||||
# Builder image
|
||||
FROM alpine:latest AS builder
|
||||
FROM node:16-alpine as builder
|
||||
|
||||
ARG VERSION
|
||||
ARG REPOSITORY=directus/directus
|
||||
|
||||
# Get runtime dependencies from optional dependencies
|
||||
# defined in package.json of Directus API package
|
||||
WORKDIR /directus
|
||||
RUN apk add --no-cache jq \
|
||||
&& wget -O directus-api-package.json "https://raw.githubusercontent.com/${REPOSITORY}/${VERSION}/api/package.json" \
|
||||
&& jq '{ \
|
||||
name: "directus-project", \
|
||||
version: "1.0.0", \
|
||||
description: "Directus Project", \
|
||||
dependencies: .optionalDependencies \
|
||||
}' \
|
||||
directus-api-package.json > package.json
|
||||
COPY /dist .
|
||||
RUN npm i --only=production --no-package-lock
|
||||
RUN rm *.tgz
|
||||
|
||||
# Directus image
|
||||
FROM node:16-alpine
|
||||
@@ -54,19 +42,9 @@ ENV \
|
||||
EMAIL_SENDMAIL_PATH="/usr/sbin/sendmail"
|
||||
|
||||
RUN \
|
||||
# Install system dependencies
|
||||
# - 'bash' for entrypoint script
|
||||
# - 'ssmtp' to be able to send mails
|
||||
# - 'util-linux' not sure if this is required
|
||||
# Upgrade system and install 'ssmtp' to be able to send mails
|
||||
apk upgrade --no-cache && apk add --no-cache \
|
||||
bash \
|
||||
ssmtp \
|
||||
util-linux \
|
||||
# Install global node dependencies
|
||||
&& npm install -g \
|
||||
yargs \
|
||||
pino \
|
||||
pino-colada \
|
||||
# Create directory for Directus with corresponding ownership
|
||||
# (can be omitted on newer Docker versions since WORKDIR below will do the same)
|
||||
&& mkdir /directus && chown node:node /directus
|
||||
@@ -75,32 +53,22 @@ RUN \
|
||||
USER node
|
||||
WORKDIR /directus
|
||||
|
||||
# Get package.json from builder image
|
||||
COPY --from=builder --chown=node:node /directus/package.json .
|
||||
COPY --from=builder --chown=node:node /directus .
|
||||
|
||||
RUN \
|
||||
# Install Directus and runtime dependencies
|
||||
# (retry if it fails for some reason, e.g. release not published yet)
|
||||
for i in $(seq 15); do npm install --save-exact "directus@${VERSION}" && break || if [ $i -eq 15 ]; then exit 1; else sleep 30; fi; done && \
|
||||
npm install \
|
||||
# Create data directories
|
||||
&& mkdir -p \
|
||||
mkdir -p \
|
||||
database \
|
||||
extensions/displays \
|
||||
extensions/interfaces \
|
||||
extensions/layouts \
|
||||
extensions/modules \
|
||||
uploads
|
||||
|
||||
# Expose data directories as volumes
|
||||
VOLUME \
|
||||
/directus/database \
|
||||
/directus/extensions \
|
||||
/directus/uploads
|
||||
|
||||
# Copy rootfs files
|
||||
COPY ./rootfs /
|
||||
|
||||
EXPOSE 8055
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
ENTRYPOINT ["entrypoint"]
|
||||
CMD npx directus bootstrap && npx directus start
|
||||
@@ -10,12 +10,14 @@ repository=directus/directus
|
||||
.PHONY: build-images
|
||||
|
||||
build-images:
|
||||
npm run build
|
||||
npm run pack
|
||||
docker build \
|
||||
--build-arg VERSION=$(version) \
|
||||
--build-arg REPOSITORY=$(repository) \
|
||||
-t directus:temp \
|
||||
-f ./build-images/rootfs/directus/images/main/Dockerfile \
|
||||
./build-images/rootfs/directus/images/main
|
||||
-f ./Dockerfile \
|
||||
..
|
||||
|
||||
docker tag directus:temp $(registry)/$(repository):$(version)
|
||||
docker tag directus:temp $(registry)/$(repository):$(tag)
|
||||
41
docker/pack.js
Normal file
41
docker/pack.js
Normal file
@@ -0,0 +1,41 @@
|
||||
const { execSync } = require('child_process');
|
||||
const { writeFileSync, mkdirSync, existsSync } = require('fs');
|
||||
const path = require('path/posix');
|
||||
|
||||
const lernaListResult = execSync('npx lerna list --json'); //The "proper" way to do this with --include-dependencies and --scope won't work here because it includes devDependencies!
|
||||
|
||||
const list = JSON.parse(String(lernaListResult));
|
||||
const apiPackageJSON = require(path.resolve(__dirname, '../api/package.json'));
|
||||
|
||||
const projectPackageJSON = {
|
||||
name: 'directus-project',
|
||||
private: true,
|
||||
description: 'Directus Project',
|
||||
dependencies: apiPackageJSON.optionalDependencies,
|
||||
};
|
||||
|
||||
const directusPackage = list.find((list) => list.name === 'directus');
|
||||
|
||||
if (!existsSync('dist')) {
|
||||
mkdirSync('dist');
|
||||
}
|
||||
|
||||
function addPackageRecursive(package) {
|
||||
const tarName = String(
|
||||
execSync(`npm pack ${package.location}`, { cwd: path.resolve(__dirname, '..', 'dist') })
|
||||
).trim();
|
||||
projectPackageJSON.dependencies[package.name] = `file:${tarName}`;
|
||||
const packageJSON = require(path.join(package.location, 'package.json'));
|
||||
Object.keys(packageJSON.dependencies || {}).forEach((dependencyName) => {
|
||||
if (!projectPackageJSON.dependencies[dependencyName]) {
|
||||
const package = list.find((list) => list.name === dependencyName);
|
||||
if (package) {
|
||||
addPackageRecursive(package);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addPackageRecursive(directusPackage);
|
||||
|
||||
writeFileSync(path.resolve(__dirname, '../dist/package.json'), JSON.stringify(projectPackageJSON, null, 4));
|
||||
@@ -805,6 +805,11 @@ module.exports = {
|
||||
path: '/contributing/running-locally',
|
||||
title: 'Running Locally',
|
||||
},
|
||||
{
|
||||
type: 'page',
|
||||
path: '/contributing/github-ci',
|
||||
title: 'GitHub CI',
|
||||
},
|
||||
{
|
||||
type: 'page',
|
||||
path: '/contributing/translations',
|
||||
|
||||
48
docs/contributing/github-ci.md
Normal file
48
docs/contributing/github-ci.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# GitHub CI
|
||||
|
||||
> This guide explains how to publish a forked version of Directus on NPM, dockerhub and GHCR. You need to first
|
||||
> [create a fork](/contributing/running-locally/)
|
||||
|
||||
::: warning Using a fork in production is neither supported nor recommended.
|
||||
|
||||
Only do so if:
|
||||
|
||||
1. The feature you want to implement doesn't satisfy the 80/20 principle
|
||||
2. There is a technical limitation preventing you from implementing it as an extension
|
||||
|
||||
Forks are not officially supported - please don't submit fork-specific bugs and questions on the official repo.
|
||||
|
||||
If you suspect a bug to not be part of your changes please confirm this by reproducing it with the official version
|
||||
**before** submitting an issue.
|
||||
|
||||
:::
|
||||
|
||||
::: tip Minimum Requirements
|
||||
|
||||
If you want to publish your fork to hub.docker.com or NPM you need to have an account there.
|
||||
|
||||
Note: to publish to NPM you probably have to change all the package names. Publishing to NPM should almost never be
|
||||
necessary.
|
||||
|
||||
:::
|
||||
|
||||
## 1. Setup environment variables/secrets
|
||||
|
||||
## General
|
||||
|
||||
| Variable | Description | Example |
|
||||
| ----------------- | ---------------------------------------------------------------------- | --------------------------- |
|
||||
| `GHCR_IMAGE` | Image name for GitHub Container Registry. Be sure to use the full URL. | `ghcr.io/directus/directus` |
|
||||
| `DOCKERHUB_IMAGE` | Image name for hub.docker.com, no prefix. | `directus/directus` |
|
||||
|
||||
| Secret | Description | Example |
|
||||
| -------------------- | ------------------------------------------------------- | -------------- |
|
||||
| `NPM_TOKEN` | Your NPM token. Make sure to use the type "automation". | `12345678-...` |
|
||||
| `DOCKERHUB_USERNAME` | Dockerhub Username | `directus` |
|
||||
| `DOCKERHUB_TOKEN` | Dockerhub Password | `hunter2` |
|
||||
|
||||
## 2. Create a release
|
||||
|
||||
```bash
|
||||
npm run release
|
||||
```
|
||||
@@ -74,6 +74,7 @@ issue doesn't already exist, you can [submit a bug report](https://github.com/di
|
||||
Issues. Please ensure the following for all submissions:
|
||||
|
||||
- You are experiencing an actual bug, not a configuration issue
|
||||
- You are using the official (pre-built) version of directus and not a fork
|
||||
- You are not asking a question or requesting a new feature
|
||||
- You have checked that no similar issue already exists
|
||||
- You have entered a clear and concise title
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"format": "prettier --write \"**/*.{js,ts,vue,md,yaml}\"",
|
||||
"dev": "lerna run dev --stream --parallel",
|
||||
"build": "lerna run build",
|
||||
"pack": "node docker/pack",
|
||||
"release": "lerna publish --force-publish --exact",
|
||||
"test": "lerna run test",
|
||||
"test:e2e": "jest tests -c tests/jest.config.js",
|
||||
|
||||
Reference in New Issue
Block a user