Skip to content

Commit

Permalink
CICD initial commit
Browse files Browse the repository at this point in the history
Signed-off-by: Ivan Kuznetsov <[email protected]>
  • Loading branch information
jsvapiav committed Apr 3, 2024
1 parent c25a928 commit 3e7d7dc
Show file tree
Hide file tree
Showing 9 changed files with 470 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .github/actions/build-action/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Container image that runs your code
FROM ubuntu:22.04

ENV TZ=Europe/Helsinki

RUN apt-get update && apt-get -y install curl xz-utils git

# Install nixos
COPY install_nix.sh /install_nix.sh
RUN /install_nix.sh

# Copies your code file from your action repository to the filesystem path `/` of the container
COPY entrypoint.sh /entrypoint.sh

# Code file to execute when the docker container starts up (`entrypoint.sh`)
ENTRYPOINT ["/entrypoint.sh"]

29 changes: 29 additions & 0 deletions .github/actions/build-action/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# SPDX-FileCopyrightText: 2022-2024 TII (SSRC) and the Ghaf contributors
#
# SPDX-License-Identifier: Apache-2.0

name: 'Build FMO-OS image'
description: 'Build an FMO-OS image'

inputs:
build_target:
description: 'Build target name'
required: true
CACHIX_TOKEN:
description: 'cachix binary cache token'
required: true
RA_TOKEN:
description: 'RA deployment token'
required: true
outputs:
outimg:
description: 'Result image path in workdir'

runs:
using: 'docker'
image: 'Dockerfile'
args:
- ${{ inputs.build_target }}
- ${{ inputs.CACHIX_TOKEN }}
- ${{ inputs.RA_TOKEN }}

84 changes: 84 additions & 0 deletions .github/actions/build-action/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/bin/sh -l
# SPDX-FileCopyrightText: 2022-2024 TII (SSRC) and the Ghaf contributors
#
# SPDX-License-Identifier: Apache-2.0

BUILD_TARGET=$1
CACHIX_TOKEN=$2
RA_TOKEN=$3

SSH_DIR="/root/.ssh/"
RESULT_DIR="result/iso/"
RESULT_NAME="nixos.iso"
RESULT_COPY_DIR="./result_to_upload/"
SYS_USER_NAME="root"

err_print() {
printf "%s" "$*" >&2
}

err_exit() {
local rc=$1
shift
err_print "$@"
exit "$rc"
}

echo "build target: $BUILD_TARGET"
cd $GITHUB_WORKSPACE

echo "::group::Input validation"
[ ! "$BUILD_TARGET" ] && err_exit 1 "BUILD_TARGET undefined"
[ ! "$CACHIX_TOKEN" ] && err_exit 1 "CACHIX_TOKEN undefined"
[ ! "$RA_TOKEN" ] && err_exit 1 "RA_TOKEN undefined"
echo "::endgroup::"

echo "::group::Install cachix"
nix-env -iA cachix -f https://cachix.org/api/v1/install
echo "Using cachix version:"
cachix --version || err_exit 1 "Cachix intallation has failed. Fail"
echo "::endgroup::"

echo "::group::Use FMO-OS cachix"
export USER=$SYS_USER_NAME
cachix authtoken $CACHIX_TOKEN
cachix use fmo-os || err_exit 1 "Cachix authentication has failed. Fail"
echo "::endgroup::"

echo "::group::Install RA deployment token"
# WAR: adding deployment token as user's ssh key
# Need a better way to do that
mkdir -p $SSH_DIR
echo "$RA_TOKEN" > $SSH_DIR/id_rsa
chmod 600 $SSH_DIR/id_rsa
echo "::endgroup::"

echo "::group::Add github to knownhosts"
mkdir -p $SSH_DIR
ssh-keyscan -t ed25519 -H github.com > $SSH_DIR/known_hosts
chmod 600 $SSH_DIR/known_hosts
echo "::endgroup::"

echo "::group::Build $BUILD_TARGET"
nix flake show
cachix watch-exec fmo-os -- \
nix build -L --accept-flake-config .#$BUILD_TARGET
echo "::endgroup::"

echo "::group::Nix collect garbage"
nix-collect-garbage
echo "::endgroup::"

echo "::group::Copy results"
out=$(readlink -f $RESULT_DIR/$RESULT_NAME)
mkdir -p $RESULT_COPY_DIR
cp $out $RESULT_COPY_DIR/$RESULT_NAME || err_exit 1 "Result copy failed. Fail"
out=$(ls $RESULT_COPY_DIR/$RESULT_NAME)
echo "::endgroup::"


echo "::group::Validate out"
[ ! "$out" ] && err_exit 1 "There is no image has been built. Fail"

echo "outimg=$out" >> $GITHUB_OUTPUT
echo "::endgroup::"
101 changes: 101 additions & 0 deletions .github/actions/build-action/install_nix.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/usr/bin/env bash

# Based on install-nix-action by Cachix.
# See:
# https://github.com/cachix/install-nix-action/blob/master/install-nix.sh

# shellcheck shell=bash

NIX_VERSION='2.18.1'

set -euo pipefail

# Check if Nix is already installed
if nix_path="$(type -p nix || command -v nix)"; then
echo "Aborting: Nix is already installed at ${nix_path}"
exit
fi

echo "Installing Nix version ${NIX_VERSION}"

# Create a temporary workdir
workdir=$(mktemp -d)
trap 'rm -rf "$workdir"' EXIT

# Helper function for writing Nix configuration
function add_config() {
[[ -n $1 ]] && echo "$1" >>"${workdir}/nix.conf"
}

# Add header comment
add_config "# Nix configuration reference:"
add_config "# https://nixos.org/manual/nix/stable/command-ref/conf-file.html"

# Basic config
add_config "experimental-features = nix-command flakes repl-flake"
add_config "system-features = nixos-test benchmark big-parallel kvm"
add_config "use-xdg-base-directories = true"
add_config "extra-nix-path = nixpkgs=flake:nixpkgs"

# Allow binary caches for user
add_config "trusted-users = root ${USER-}"

# Add default NixOS binary cache
add_config "substituters = https://cache.nixos.org/ https://cache.vedenemo.dev"
add_config "trusted-substituters = https://cache.nixos.org/"
add_config "trusted-public-keys = cache.vedenemo.dev:8NhplARANhClUSWJyLVk4WMyy1Wb4rhmWW2u8AejH9E= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
add_config "substitute = true"

# Optimize store disk usage
# add_config "auto-optimise-store = true"

# Set GC thresholds to instruct Nix to do GC if available disk-space
# in '/nix/store' drops below 'min-free' bytes during build.
# Nix keeps doing GC until there is no more garbage, or until 'max-free'
# bytes of disk space is available.
# add_config "min-free = $((25 * 1024 * 1024 * 1024))"
# add_config "max-free = $((50 * 1024 * 1024 * 1024))"

# Keep compilers, derivations and such when running GC.
# Also show stack trace on evaluation errors.
# add_config "keep-outputs = true"
# add_config "keep-derivations = true"
add_config "show-trace = true"

# Enable sandbox feature
add_config "sandbox = true"

# Maximum number of Nix jobs to build in parallel, 'auto' uses all available CPUs.
add_config "max-jobs = auto"

# This option controls the the parallelism of the builders, enabling
# parallel building at the discretion of the builders (by setting the
# NIX_BUILD_CORES env variable). For example for GNU Make this works
# just like passing the '-jN' flag to Make. Setting of '0' means
# use all available CPUs.
add_config "cores = 0"

unset -f add_config

# Nix installer flags
installer_options=(
--nix-extra-conf-file "${workdir}/nix.conf"
--daemon
--yes
)

echo "Nix installer options:"
echo "${installer_options[*]}"

# There is --retry-on-errors, but only newer curl versions support that
curl_retries=5
while ! curl -sS -o "${workdir}/install" -v --fail -L "https://releases.nixos.org/nix/nix-${NIX_VERSION}/install"; do
sleep 1
((curl_retries--))
if [[ ${curl_retries} -le 0 ]]; then
echo "curl retries failed" >&2
exit 1
fi
done

sh "${workdir}/install" "${installer_options[@]}"
39 changes: 39 additions & 0 deletions .github/actions/upload-action/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# SPDX-FileCopyrightText: 2022-2024 TII (SSRC) and the Ghaf contributors
#
# SPDX-License-Identifier: Apache-2.0

name: Push artifacts to JFrog artifactory
description: Push artifacts to JFrog artifactory

inputs:
JFROG_UNAME:
description: 'user account for artifactory'
required: true
JFROG_TOKEN:
description: 'api-key for artifactory'
required: true
JFROG_URL:
description: 'artifactory url'
required: true
build-num:
description: 'build number'
required: false
input-paths:
description: 'input-paths'
required: true

runs:
using: "composite"
steps:
- name: Preparing artifactory for upload
uses: "jfrog/setup-jfrog-cli@v3"
- run: echo "${{ github.action_path }}" >> $GITHUB_PATH
shell: bash
- run: upload.sh
env:
JFROG_UNAME: ${{ inputs.JFROG_UNAME }}
JFROG_TOKEN: ${{ inputs.JFROG_TOKEN }}
JFROG_URL: ${{ inputs.JFROG_URL }}
BUILD_NUM: ${{ inputs.build-num }}
INPUT_PATHS: ${{ inputs.input-paths }}
shell: bash
49 changes: 49 additions & 0 deletions .github/actions/upload-action/upload.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/bin/bash -e
# Copyright 2024, Technology Innovation Institute

err_print() {
printf "%s" "$*" >&2
}

err_exit() {
local rc=$1
shift
err_print "$@"
exit "$rc"
}

echo "::group::Input validation"

[ ! "$JFROG_URL" ] && err_exit 1 "JFROG_URL undefined"
[ ! "$JFROG_UNAME" ] && err_exit 1 "JFROG_UNAME undefined"
[ ! "$JFROG_TOKEN" ] && err_exit 1 "JFROG_TOKEN undefined"

for input in $INPUT_PATHS; do
SOURCE_DIR=$(echo "$input" | cut -d ":" -f 1)
DEST_DIR=$(echo "$input" | cut -d ":" -f 2)
echo "SOURCE_DIR=$SOURCE_DIR"
echo "DEST_DIR=$DEST_DIR"
[ ! "$SOURCE_DIR" ] && err_exit 1 "SOURCE_DIR undefined"
[ ! "$DEST_DIR" ] && err_exit 1 "SOURCE_DIR undefined"
done

echo "::endgroup::"
echo "::group::Artifact upload"

jf c add --url "$JFROG_URL" --user "$JFROG_UNAME" --access-token "$JFROG_TOKEN"
jf rt ping

for input in $INPUT_PATHS; do
SOURCE_DIR=$(echo "$input" | cut -d ":" -f 1)
DEST_DIR=$(echo "$input" | cut -d ":" -f 2)

UPLOAD_DIR=$SOURCE_DIR
if [ "$BUILD_NUM" ]; then
UPLOAD_DIR=$SOURCE_DIR-b$BUILD_NUM
mv "$SOURCE_DIR" "$UPLOAD_DIR"
fi
echo "Run: jf rt u "$UPLOAD_DIR" "$DEST_DIR" --flat=true"
jf rt u "$UPLOAD_DIR" "$DEST_DIR" --flat=true
done

echo "::endgroup::"
60 changes: 60 additions & 0 deletions .github/workflows/build-yml-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# SPDX-FileCopyrightText: 2023-2024 TII (SSRC) and the Ghaf contributors
#
# SPDX-License-Identifier: Apache-2.0

on:
workflow_call:
outputs:
result:
value: ${{ jobs.check.outputs.result }}
pull_request:
branches:
- main

jobs:
check:
runs-on: ubuntu-latest
outputs:
result: ${{ steps.set-output.outputs.result }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Check if build.yml is modified
id: build-yml-changed
uses: tj-actions/changed-files@v40
with:
files: .github/**
- name: Set output
id: set-output
run: |
# Not changed
if [ "${{ steps.build-yml-changed.outputs.any_changed }}" != "true" ];
then
echo "result=not-changed"
echo "result=not-changed" >> "$GITHUB_OUTPUT"
exit 0
fi
# Changed from external PR
if [ "${{ github.event_name }}" = "pull_request_target" ] && \
[ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ];
then
echo "::error::" \
"You are trying to edit workflow or action file" \
"This step will fail to notify the team about that accident" \
"Files changed during this event: ${{ steps.changed-files-yaml.outputs.test_all_changed_files }}"
echo "result=changed-from-fork"
echo "result=changed-from-fork" >> "$GITHUB_OUTPUT"
exit 1
fi
# Changed from internal PR
echo "::error::" \
"You are trying to edit workflow or action file" \
"This step will fail to notify the team about that accident" \
"Files changed during this event: ${{ steps.changed-files-yaml.outputs.test_all_changed_files }}"
echo "result=changed-from-internal"
echo "result=changed-from-internal" >> "$GITHUB_OUTPUT"
exit 1
Loading

0 comments on commit 3e7d7dc

Please sign in to comment.