From 2f3b50021ba3443bb73719bf0a258829571a6c3f Mon Sep 17 00:00:00 2001 From: Albert Westra Date: Tue, 13 Feb 2024 01:57:37 -0800 Subject: [PATCH] First Draft of Script This is my first draft of the script. I'll probably need to edit and make more changes, but this is a start. --- .github/workflows/script-build.yaml | 44 +++++ scripts/linux-build.sh | 287 ++++++++++++++++++++++++++++ 2 files changed, 331 insertions(+) create mode 100644 .github/workflows/script-build.yaml create mode 100644 scripts/linux-build.sh diff --git a/.github/workflows/script-build.yaml b/.github/workflows/script-build.yaml new file mode 100644 index 000000000..377913545 --- /dev/null +++ b/.github/workflows/script-build.yaml @@ -0,0 +1,44 @@ +name: script-build + +# This specific workflow mainly calls script funtions to do the build. This method +# should make it more modular and not dependent on github actions. Downside is that +# there would be two or more different files to maintain. Another Pro is that I can +# adjust the script with env variables for different environments. By default, +# script will assunme that is in a ubuntu environment. + +on: + - push + +jobs: + linux: + name: Linux + runs-on: ubuntu-22.04 + defaults: + run: + working-directory: scripts/ + steps: + # Checkout the repository under the correct user and set safe directory. + - name: "Checkout Repository" + uses: actions/checkout@v4 + + - name: "Make Script Executable" + run: chmod +x linux-build.sh + + - name: "Update Enviroment and Install Package Dependencies" + run: ./linux-build.sh installdeps + + #TODO Sould separate these into two separate actions. + - name: "Install libmypaint and mypaint-brushes from Source" + run: ./linux-build.sh installsourcedeps + + - name: "Build MyPaint" + run: ./linux-build.sh build + + - name: "Test MyPaint" + run: ./linux-build.sh tests + + - name: Run demo with XVFB + run: xvfb-run --auto-servernum ./linux-build.sh demo + + - name: "Clean MyPaint" + run: ./linux-build.sh clean diff --git a/scripts/linux-build.sh b/scripts/linux-build.sh new file mode 100644 index 000000000..d83b6da52 --- /dev/null +++ b/scripts/linux-build.sh @@ -0,0 +1,287 @@ +#!/usr/bin/env bash +# Linux build and test script for MyPaint. +# All rights waived: https://creativecommons.org/publicdomain/zero/1.0/ +# +#: Usage: +#: $ linux_build.sh [OPTIONS] +#: +#: OPTIONS: +#: installdeps Build+install dependencies. +#: build Build MyPaint itself from this source tree. +#: clean Clean the build tree. +#: demo Run the demo. Have Xvfb running if in a headless server. +#: tests Runs tests on the built source. Includes doctests. +#: +#: This script is designed to be called by GitHub actions, however +#: it's clean enough to run from an interactive shell. +#: +#: Script written by Albert Westra(contact@odysseywestra.com) +#: + +# This script will act similar to the windows/msys2-build.sh script. The +# main difference is that it will be using the apt-get package manager instead +# of pacman. This script will also be building from source instead of using +# pkgbuilds + +# ANSI control codes +RED='\033[0;31m' +GREEN='\033[0;32m' +CYAN='\033[0;36m' +YELLOW='\033[0;33m' +NC='\033[0m' # No Color + +# TODO: These variables below should be called from the GitHub actions +# environment. Then change this to an if statement incase those environment +# variables are not set. + +# This script pulls down and maintains a clone of the mypaint project so I need +# to keep track of the root directory of the project. This will be using ubuntu +# image from github actions and the root directory will be /home/work/mypaint/. + +# Get Remote_URL by using git. +REMOTE_URL="$(git config --get remote.origin.url)" +# Extract username from REMOTE_URL with awk. +USERNAME="$(echo $REMOTE_URL | awk -F[:/.] '{print $6}')" +# Extract Project name from REMOTE_URL with awk. +PROJECTNAME="$(echo $REMOTE_URL | awk -F[:/.] '{print $7}')" +# Grab the path the project was cloned in. +PROJECT_PATH="$(git rev-parse --show-toplevel)" +# Set the root directory of the project. +SRC_ROOT_DIR="/home/runner/work/$PROJECTNAME/$PROJECTNAME" +SRC_CLONEURI_BASE="https://github.com/$USERNAME" + +# Need to make the script for package management flexible so that it can be used +# on other systems. Need to make running sudo optional as well. + +PKG_MANAGER="apt-get" +UPDATE_CMD="sudo $PKG_MANAGER update" +UPGRADE_CMD="sudo $PKG_MANAGER upgrade" +INSTALL_CMD="sudo $PKG_MANAGER install -y" +REMOVE_CMD="sudo $PKG_MANAGER remove -y" + +# Set a package dependency list incase other OS's are used. + +DEP_LIST="g++ gettext intltool gir1.2-gtk-3.0 libgtk-3-dev libjson-c-dev \ + liblcms2-dev libpng-dev python3-dev python-gi-dev python3-gi-cairo \ + python3-nose python3-numpy python3-setuptools swig git" + +# These are just here to make the output of the script more readable in the logs. + +loginfo() { + echo -ne "${CYAN}" + echo -n "$@" + echo -e "${NC}" +} + +logok() { + echo -ne "${GREEN}" + echo -n "$@" + echo -e "${NC}" +} + +logerr() { + echo -ne "${RED}ERROR: " + echo -n "$@" + echo -e "${NC}" +} + +logwarn() { + echo -ne "${YELLOW}WARNING: " + echo -n "$@" + echo -e "${NC}" +} + +# This section makes sure that we start from the Project Source Path. +# By Default it should point to /home/runner/work/username/projectname. +# TODO: Set it so that will will work with any directory path. +cd $SRC_ROOT_DIR + if [ $? -ne 0 ]; then + logerr "Could not change to $SRC_ROOT_DIR. Exiting." + exit 1 + fi + + +# This function will be used to update the environment and upgrade the packages + +prepare_enviroment(){ + loginfo "Updating Environment packages" + $UPDATE_CMD + loginfo "Upgradeing Packages" + $UPGRADE_CMD + logok "Enviroment Upgraded" +} + +# This function will be used to install the dependencies for the project. + +install_dependencies() { + loginfo "Installing Dependencies" + if ! $INSTALL_CMD $DEP_LIST; then + logerr "Failed to install dependencies" + exit 1 + fi + logok "Dependencies installed" + + sudo ln -s /usr/lib/*/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders /usr/local/bin/gdk-pixbuf-query-loaders + sudo gdk-pixbuf-query-loaders --update-cache + logok "Pixbuf query loaders cache updated" +} + +# This fuction will check the remote repository for the correct branch and +# if it exists it will use the same branch. If it does not exist it will use +# the main branch. This will most likely be called from the install_from_source() +# function. + +use_correct_branch(){ + # Set the branch name + GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + + loginfo "$ is on branch $GIT_BRANCH" + + # Check if the branch exists in the first repository + git ls-remote --heads https://github.com/owner1/repo1.git $branch | grep -q refs/heads/$branch + if [ $? -eq 0 ]; then + branch=$branch + else + branch="main" + fi + + # Checkout the branches + git clone --branch $branch1 https://github.com/owner1/repo1.git repo1 +} + +# This function will be used to install the dependencies from source. Need to +# make it modular so that it can be used for other enviroment or when we change +# build procces. + +install_from_source(){ + SOURCEPKG="$1" + INSTALL="$2" + SOURCEPKG_URI="$SRC_CLONEURI_BASE/$SOURCEPKG" + loginfo "Cloning $SOURCEPKG Repository" + cd $SRC_ROOT_DIR + #Check to see if the user has forked the repository. If not use upstream. + if ! git clone --verbose $SOURCEPKG_URI; then + logwarn "User has not forked $SOURCEPKG. Using upstream repository" + git clone --verbose https://github.com/mypaint/$SOURCEPKG + fi + pushd "$SOURCEPKG" + loginfo "Building $SOURCEPKG" + ./autogen.sh + ./configure --prefix=/usr + make + if $INSTALL; then + loginfo "Installing $SOURCEPKG into Enviroment" + sudo make install + logok "Install finished" + fi + popd + loginfo "Removing $SOURCEPKG" Source from Environment + sudo rm -v -fr $SOURCEPKG +} + +build_for_testing() { + # This just build mypaint ane errors if the build fails. + loginfo "Building MyPaint from source" + if ! python3 setup.py build; then + logerr "Build failed." + exit 1 + fi + logok "Build finished." +} + +clean_local_repo() { + # This test the clean function in the setup.py file. So we have a clean + # repository to work with. + loginfo "Cleaning local build" + if ! python3 setup.py clean --all; then + logerr "Fail to clean repository." + exit 1 + fi + if ! rm -vf lib/*_wrap.c*; then + logerr "Fail to remove lib/*_wrap.c*" + exit 1 + fi + logok "Clean finished." +} + +install_test(){ + # This will test the install and uninstall fuction in the setup.py file. + # This will probably go away, but it's here for now. + loginfo "Testing setup.py managed installation commands" + loginfo "Running managed_install" + if ! sudo python3 setup.py managed_install; then + logerr "Install failed." + exit 1 + fi + logok "Install finished." + + loginfo "Running managed_uninstall" + if ! sudo python3 setup.py managed_uninstall; then + logerr "Uninstall failed." + exit 1 + fi + logok "Uninstall finished." + logok "Install-test finished finished." +} + +run_doctest() { + # This will make sure all the files in the lib directory are present and working. + loginfo "Running unit document tests." + if ! python3 setup.py nosetests --tests lib; then + logerr "Test failed." + exit 1 + fi + logok "Unit document tests done." +} + +run_tests() { + # This will run conformance test to make sure the brush engine is working. + # NOTE: Might need to run with xvfb too since it skiping certian tests. + loginfo "Running conformance tests." + if ! python3 setup.py test; then + logerr "Test failed." + exit 1 + fi + logok "Tests done." +} + +run_demo() { + # This will run the demo and quit. Use xvfb-run if you are on a headless CI. + loginfo "Running demo" + if ! MYPAINT_DEBUG=1 python setup.py demo --args='--run-and-quit'; then + logerr "Demo failed." + exit 1 + fi + logok "Demo done." +} + +case "$1" in + installdeps) + prepare_enviroment + install_dependencies + ;; + # I will probably need to make change how this works. + # Probably call directly from the yaml file instead. + installsourcedeps) + install_from_source "libmypaint" true + install_from_source "mypaint-brushes" true + ;; + build) + build_for_testing + ;; + clean) + clean_local_repo + ;; + tests) + run_tests + run_doctest + install_test + ;; + demo) + run_demo + ;; + *) + grep '^#:' $0 | cut -d ':' -f 2-19 + exit 2 + ;; +esac