Skip to content

Commit

Permalink
ci: Add initial CI
Browse files Browse the repository at this point in the history
  • Loading branch information
gabyx committed Jun 25, 2024
1 parent d440e34 commit 9784ecc
Show file tree
Hide file tree
Showing 14 changed files with 774 additions and 6 deletions.
23 changes: 23 additions & 0 deletions .github/pipeline.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: rdf-protect

on: [push]

jobs:
trigger-gitlab:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Mirror + Trigger CI
uses: SvanBoxel/gitlab-mirror-and-ci-action@master
with:
args: "https://gitlab.com/<namespace>/<repository>"
env:
FOLLOW_TAGS: "false"
FORCE_PUSH: "true"
GITLAB_HOSTNAME: "gitlab.datascience.ch"
GITLAB_USERNAME: ${{ secrets.GITLAB_USERNAME }}
GITLAB_PASSWORD: ${{ secrets.GITLAB_PASSWORD }}
GITLAB_PROJECT_ID: "454"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions .gitlab/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
local
37 changes: 37 additions & 0 deletions .gitlab/container/Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# This is a docker image containing docker and a Nix store.
# This enables to either run Docker images inside this one,
# or use `nix develop` to start a sandboxed environment to
# do other non-docker related stuff.

FROM alpine:latest as base-podman
LABEL org.opencontainers.image.source https://github.com/sdsc-ordes/rdf-protect
LABEL org.opencontainers.image.description "CI container image for rdf-protect"
LABEL org.opencontainers.image.license "Apache"

RUN apk add findutils coreutils git jq curl bash just parallel podman

# Nix Image
# ===============================================
FROM base-podman as ci-nix
RUN [ "TARGETPLATFORM" = "linux/amd64" ] || echo "Platform not yet supported."
COPY ./tools /container-setup

# Install Nix and pre-cache the env.
RUN bash -c ". /container-setup/general.sh && ci_setup_nix"
COPY rust-toolchain.toml /container-setup/
RUN cd /container-setup && \
git init && git add . && \
nix --accept-flake-config \
build --no-link "./tools/nix#devShells.x86_64-linux.ci"

# Format image.
# ===============================================
FROM ci-nix as ci-format

# Lint image.
# ===============================================
FROM ci-nix as ci-lint

# Build image.
# ===============================================
FROM ci-nix as ci-build
44 changes: 44 additions & 0 deletions .gitlab/pipeline.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
stages:
- lint
- format
- build

.defaults-rules: &defaults-rules
- if: "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature|bugfix/ ||
$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH"
when: always

.main-rules: &main-rules
- if: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH"
when: always

lint:
stage: lint
needs: []
image: ghcr.io/sdsc-ordes/rdf-protect:ci-lint-1.0.0
rules:
- *defaults-rules
script:
- source .gitlab/scripts/before-script.sh
- nix develop .#ci --command just lint

format:
stage: format
needs: []
image: ghcr.io/sdsc-order/rdf-protect:ci-format-1.0.0
rules:
- *defaults-rules
script:
- source .gitlab/scripts/before-script.sh
- nix develop .#ci --command just format-general
- nix develop .#ci --command just format

build:
stage: build
needs: []
image: ghcr.io/sdsc-ordes/rdf-protect:ci-build-1.0.0
rules:
- *defaults-rules
script:
- source .gitlab/scripts/before-script.sh
- nix develop .#ci --command just build
11 changes: 11 additions & 0 deletions .gitlab/scripts/before-script.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090,SC1091
# This script is sourced.
set -u

ROOT_DIR=$(git rev-parse --show-toplevel)
. "$ROOT_DIR/tools/general.sh"

ci_container_mgr_setup

unset ROOT_DIR
39 changes: 39 additions & 0 deletions .gitlab/scripts/upload-images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090,SC1091
set -e
set -u

ROOT_DIR=$(git rev-parse --show-toplevel)
. "$ROOT_DIR/tools/general.sh"

cd "$ROOT_DIR"

function build_ci_image() {
local image_type="$1"
local repository="$2"
local tag="$image_type-$3"

local image_name="$repository:$tag"

print_info "Building image '$image_name'."

ci_container_mgr build -f "$container_file" \
--target "$image_type" \
-t "$image_name" \
. || die "Could not build image."

ci_container_mgr push -f "$image_name" || die "Could not upload image."
}

repository="${1:-ghcr.io/sdsc-ordes/rdf-protect}"
tag="${2:-1.0.0}"
container_file=".gitlab/container/Containerfile"

if [ "${CI:-}" = "true" ]; then
ci_container_mgr_login "$DOCKER_REPOSITORY_READ_USERNAME" "$DOCKER_REPOSITORY_READ_TOKEN"
fi

readarray -t images < <(grep -E "as ci-.*" "$container_file" | sed -E 's@.*as (ci-.*)$@\1@g')
for image in "${images[@]}"; do
build_ci_image "$image" "$repository" "$tag"
done
19 changes: 15 additions & 4 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ container_mgr := "podman"

# Enter a Nix development shell.
nix-develop:
cd "{{root_dir}}" && nix develop ./nix#default
cd "{{root_dir}}" && nix develop ./tools/nix#default

# Build the executable.
build *args:
Expand All @@ -23,7 +23,18 @@ watch:
run:
cd "{{root_dir}}" && cargo run "${@:1}"

format:
format-general *args:
# Not implemented yet.
true

format *args:
cd "{{comp_dir}}" && \
"{{root_dir}}/tools/format-rust.sh" {{args}}

lint *args:
cd "{{comp_dir}}" && \
"{{root_dir}}/tools/lint-rust.sh" {{args}}

upload-ci-images:
cd "{{root_dir}}" && \
{{container_mgr}} run -v "{{root_dir}}:/repo" -v "$(pwd):/workspace" -w "/workspace" \
instrumentisto/rust:nightly-alpine cargo fmt -- --config-path /repo
.gitlab/scripts/upload-images.sh
15 changes: 15 additions & 0 deletions tools/format-rust.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090,SC1091
set -e
set -u

ROOT_DIR=$(git rev-parse --show-toplevel)
. "$ROOT_DIR/tools/general.sh"

cd "$ROOT_DIR"

print_info "Run Rust format."
ci_wrap_container \
ghcr.io/sdsc-ordes/rdf-protect:ci-format-1.0.0 \
nix develop ./tools/nix#ci --command \
cargo fmt "$@"
186 changes: 186 additions & 0 deletions tools/general.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090,SC1091
# shellcheck disable=SC2154,SC2086

function _print() {
local color="$1"
local flags="$2"
local header="$3"
shift 3

local hasColor="0"
if [ "${FORCE_COLOR:-}" != 1 ]; then
[ -t 1 ] && hasColor="1"
else
hasColor="1"
fi

if [ "$hasColor" = "0" ] || [ "${LOG_COLORS:-}" = "false" ]; then
local msg
msg=$(printf '%b\n' "$@")
msg="${msg//$'\n'/$'\n' }"
echo $flags -e "-- $header$msg"
else
local s=$'\033' e='[0m'
local msg
msg=$(printf "%b\n" "$@")
msg="${msg//$'\n'/$'\n' }"
echo $flags -e "${s}${color}-- $header$msg${s}${e}"
fi
}
function print_info() {
_print "[0;94m" "" "" "$@"
}

function print_warning() {
_print "[0;31m" "" "WARN: " "$@" >&2
}

function print_error() {
_print "[0;31m" "" "ERROR: " "$@" >&2
}

function die() {
print_error "$@"
exit 1
}

function ci_is_running() {
if [ "${CI:-}" = "true" ]; then
return 0
fi

return 1
}

function ci_wrap_container() {
local container="$1"
shift 1
local cmd=("$@")

if [ "$OSTYPE" = "nixos" ]; then
"${cmd[@]}"
else
ci_container_mgr_run_mounted "$(pwd)" "$container" "${cmd[@]}"
fi
}

function ci_setup_githooks() {
local installPrefix="${1:-$CI_BUILDS_DIR/githooks}"
mkdir -p "$installPrefix"

print_info "Install Githooks in '$installPrefix'."
githooks-cli installer --non-interactive --prefix "$installPrefix"

git hooks config enable-containerized-hooks --global --set
git hooks config container-manager-types --global --set "podman,docker"

print_info "Pull all shared Githooks repositories."
git hooks shared update

export CI_GITHOOKS_INSTALL_PREFIX="$installPrefix"
}

function ci_setup_nix() {
local install_prefix="${1:-/usr/sbin}"

print_info "Install Nix."
apk add curl bash xz shadow
sh <(curl -L https://nixos.org/nix/install) --daemon --yes
cp /root/.nix-profile/bin/* "$install_prefix/"

print_info "Enable Features for Nix."
mkdir -p ~/.config/nix
{
echo "experimental-features = nix-command flakes"
echo "accept-flake-config = true"
} >~/.config/nix/nix.conf
}

# Run the container manager which is defined.
function ci_container_mgr() {
if command -v podman &>/dev/null; then
echo -e "Running podman as:\n$(printf "'%s' " "podman" "$@")" >&2
podman "$@"
else
echo -e "Running docker as:\n$(printf "'%s' " "docker" "$@")"
docker "$@"
fi
}

# Define the container id `CI_JOB_CONTAINER_ID` where
# this job runs. Useful to mount same volumes as in
# this container with `ci_run_podman`.
function ci_container_mgr_setup() {
export CONTAINER_HOST="unix://var/run/podman.sock"
print_info "Container host: '$CONTAINER_HOST'"

job_container_id=$(ci_container_mgr ps \
--filter "label=com.gitlab.gitlab-runner.type=build" \
--filter "label=com.gitlab.gitlab-runner.job.id=$CI_JOB_ID" \
--filter "label=com.gitlab.gitlab-runner.project.id=$CI_PROJECT_ID" \
--filter "label=com.gitlab.gitlab-runner.pipeline.id=$CI_PIPELINE_ID" \
--format "{{ .ID }}") ||
die "Could not find 'build' container for job id: '$CI_JOB_ID'."

[ -n "$job_container_id" ] || die "Job id is empty."

export CI_JOB_CONTAINER_ID="$job_container_id"
print_info "Job container id: '$CI_JOB_CONTAINER_ID'"
}

function ci_container_mgr_login() {
local user="$1"
local token="$2"

[ -n "$token" ] || die "Docker login token is empty"
echo "$token" |
ci_container_mgr login --password-stdin --username "$user" ||
die "Could not log into docker."
}

# Run container mgr. In CI with volume mount from the
# current build container `CI_JOB_CONTAINER_ID`.
function ci_container_mgr_run() {
if ci_is_running; then
ci_container_mgr run --volumes-from "$CI_JOB_CONTAINER_ID" "$@"
else
ci_container_mgr run "$@"
fi
}

function ci_container_mgr_run_mounted() {
local repo workspace_rel in_cmd
repo=$(git rev-parse --show-toplevel)
workspace_rel=$(cd "$1" && pwd)
workspace_rel=$(realpath --relative-to "$repo" "$workspace_rel")

shift 1
in_cmd=("$@")

local mnt_args=()
local cmd=()

if ! ci_is_running; then
cmd=("${in_cmd[@]}")
mnt_args+=(-v "$repo:/repo")
mnt_args+=(-w "/repo/$workspace_rel")
else
# Not needed to mount anything, since already existing
# under the same path as `repo`.
#
# All `/repo` and `/workspace` paths in
# command given are replaced with correct
# paths to mounted volume in CI
for arg in "${in_cmd[@]}"; do
cmd+=("$(echo "$arg" |
sed -E \
-e "s@/workspace@$workspace_rel@g" \
-e "s@/repo@$repo@g")")
done

mnt_args+=(-w "$repo/$workspace_rel")
fi

ci_container_mgr_run "${mnt_args[@]}" "${cmd[@]}"
}
Loading

0 comments on commit 9784ecc

Please sign in to comment.