add actions and workflows

This commit is contained in:
WoLfulus
2020-09-23 04:03:13 -03:00
parent 1d168ff878
commit 4501659865
15 changed files with 882 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
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

15
.github/actions/build-images/Dockerfile vendored Normal file
View File

@@ -0,0 +1,15 @@
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"]

31
.github/actions/build-images/action.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: "Build and publish Directus images"
description: "GitHub Action to publish Directus container images."
branding:
icon: archive
color: gray-dark
inputs:
username:
description: "Repository user"
required: true
password:
description: "Repository password"
required: true
version:
description: "Version"
required: true
push:
description: "Push"
required: false
default: "false"
runs:
using: "docker"
image: "Dockerfile"
args:
- --username
- ${{ inputs.username }}
- --password
- ${{ inputs.password }}
- --version
- ${{ inputs.version }}
- --push
- ${{ inputs.push }}

View File

@@ -0,0 +1,2 @@
.dockerignore
Dockerfile

View File

@@ -0,0 +1,13 @@
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

View File

@@ -0,0 +1,92 @@
#
# Builder
#
FROM node:14-alpine AS builder
ARG VERSION
RUN \
apk update && \
apk upgrade && \
apk add jq
WORKDIR /directus
COPY package.json .
RUN \
jq ".dependencies.directus = \"^${VERSION}\"" package.json > updated.json && \
mv updated.json package.json
RUN cat package.json
#
# Image
#
FROM node:14-alpine
ARG VERSION
LABEL directus.version="${VERSION}"
ENV \
PORT=41201 \
PUBLIC_URL="/" \
DB_CLIENT="sqlite3" \
DB_FILENAME="/directus/database/data.db" \
RATE_LIMITER_ENABLED="false" \
RATE_LIMITER_STORE="memory" \
RATE_LIMITER_POINTS="25" \
RATE_LIMITER_DURATION="1" \
CACHE_ENABLED="false" \
STORAGE_LOCATIONS="local" \
STORAGE_LOCAL_PUBLIC_URL="/uploads" \
STORAGE_LOCAL_DRIVER="local" \
STORAGE_LOCAL_ROOT="/directus/uploads" \
ACCESS_TOKEN_TTL="15m" \
REFRESH_TOKEN_TTL="7d" \
REFRESH_TOKEN_COOKIE_SECURE="false" \
REFRESH_TOKEN_COOKIE_SAME_SITE="lax" \
OAUTH_PROVIDERS="" \
EXTENSIONS_PATH="/directus/extensions" \
EMAIL_FROM="no-reply@directus.io" \
EMAIL_TRANSPORT="sendmail" \
EMAIL_SENDMAIL_NEW_LINE="unix" \
EMAIL_SENDMAIL_PATH="/usr/sbin/sendmail"
RUN \
apk update && \
apk upgrade && \
apk add bash ssmtp util-linux
SHELL ["/bin/bash", "-c"]
WORKDIR /directus
# Global requirements
RUN npm install -g yargs pino pino-colada
# Install Directus
COPY --from=builder /directus/package.json .
RUN npm install
# Copy files
COPY ./rootfs /
RUN chmod +x /usr/bin/entrypoint && chmod +x /usr/bin/print
# Create directories
RUN \
mkdir -p extensions/displays && \
mkdir -p extensions/interfaces && \
mkdir -p extensions/layouts && \
mkdir -p extensions/modules && \
mkdir -p database && \
mkdir -p uploads
EXPOSE 41201
VOLUME \
/directus/database \
/directus/extensions \
/directus/uploads
ENTRYPOINT ["entrypoint"]

View File

@@ -0,0 +1,22 @@
{
"name": "directus-project",
"version": "1.0.0",
"description": "Directus Project",
"main": "index.js",
"scripts": {},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"@keyv/redis": "^2.1.2",
"directus": "^9.0.0-beta.1",
"ioredis": "^4.17.3",
"memcached": "^2.2.2",
"mssql": "^6.2.2",
"mysql": "^2.18.1",
"oracledb": "^5.0.0",
"pg": "^8.3.3",
"sqlite3": "^5.0.0",
"yargs": "^16.0.3"
}
}

View File

@@ -0,0 +1,110 @@
#!/usr/bin/env bash
set -e
function seed() {
# TODO: move users to a separate check, outside database installation
local show=false
local email=${DIRECTUS_ADMIN_EMAIL:-"admin@example.com"}
local password=${DIRECTUS_ADMIN_PASSWORD:-""}
if [ "${password}" == "" ] ; then
password=$(node -e 'console.log(require("nanoid").nanoid(12))')
show=true
fi
print --level=info "Creating administrator role"
local role=$(npx directus roles create --name Administrator --admin)
print --level=info "Creating administrator user"
local user=$(npx directus users create --email "${email}" --password "${password}" --role "${role}")
if [ "${show}" == "true" ] ; then
print --level=info --stdin <<MSG
>
> Email: $email
> Password: $password
>
MSG
else
print --level=info --stdin <<MSG
>
> Email: $email
> Password: <env>
>
MSG
fi
}
function bootstrap() {
local warn=false
if [ "${KEY}" == "" ] ; then
export KEY=$(uuidgen)
warn=true
fi
if [ "${SECRET}" == "" ] ; then
export SECRET=$(node -e 'console.log(require("nanoid").nanoid(32))')
warn=true
fi
if [ "${warn}" == "true" ] ; then
print --level=warn --stdin <<WARN
>
> WARNING!
>
> The KEY and SECRET environment variables are not set.
> Some temporar
y variables were generated to fill the gap,
> but in production this is going to cause problems.
>
> Please refer to the docs at https://docs.directus.io/
> on how and why to configure them properly
>
WARN
fi
# Install database if using sqlite and file doesn't exist
if [ "${DB_CLIENT}" == "sqlite3" ] ; then
if [ "${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
should_seed=false
set +e
npx directus database install 2>&1 /dev/null
if [ "$?" == "0" ] ; then
print --level=info "Database installed"
should_seed=true
fi
set -e
if [ "${should_seed}" == "true" ] ; then
seed
fi
}
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}" $@

View File

@@ -0,0 +1,48 @@
#!/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._);
}
})();

View File

@@ -0,0 +1,115 @@
#!/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")
repository=$(argument repository "ghcr.io")
image=$(argument image "directus/directus")
version=$(argument version "")
context=$(argument context ".")
# 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})
# login into registry
docker login -u "${username}" -p "${password}" "${repository}"
docker build \
-t directus:main \
--build-arg VERSION=${version} \
/directus/images/main
if [ "${latest}" == "true" ]; then
docker tag directus:main "${repository}/${image}:latest"
if [ "${push}" == "true" ]; then
#docker push ${image}
echo "should push"
fi
fi
for tag in $tags
do
docker tag directus:main "${repository}/${image}:${tag}"
if [ "${push}" == "true" ]; then
#docker push ${image}
echo "should push"
fi
done
exit $?
}
main
exit $?

View File

@@ -0,0 +1,98 @@
#
# 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 $?
}

View File

@@ -0,0 +1,284 @@
#!/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

19
.github/workflows/build-images.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: build-images
on:
release:
types:
- created
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Build
uses: ./.github/actions/build-images
with:
username: ${{ github.actor }}
password: ${{ github.token }}
version: ${{ github.ref }}