diff --git a/.github/workflows/setup-project.yaml b/.github/workflows/setup-project.yaml new file mode 100644 index 00000000..6c96cc56 --- /dev/null +++ b/.github/workflows/setup-project.yaml @@ -0,0 +1,45 @@ +name: Create scaf project + +on: [push] + +jobs: + build-and-push: + environment: dev + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_ACCESS_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v2 + with: + push: true + tags: sixfeetup/scaf:${{ github.sha }} + + setup: + environment: dev + needs: build-and-push + runs-on: ubuntu-latest + + steps: + - name: Install Requirements + shell: bash + run: | + INSTALL_URL="https://raw.githubusercontent.com/sixfeetup/scaf/$GITHUB_REF_NAME/install.sh" + export SCAF_SCRIPT_BRANCH=$GITHUB_REF_NAME + echo "Downloading install script from $INSTALL_URL" + curl -sSL $INSTALL_URL | sh + + - name: Create Project with Scaf + shell: bash + run: | + IMAGE_TAG=$GITHUB_SHA + echo "Running scaf with sixfeetup/scaf:$IMAGE_TAG" + /usr/local/bin/scaf myproject --no-input + diff --git a/Dockerfile b/Dockerfile index bd681342..3c2ed275 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,5 @@ COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh RUN addgroup -S scaf && adduser -s /bin/ash -S scaf -G scaf WORKDIR /home/scaf/out -RUN chown scaf:scaf /home/scaf/out ENTRYPOINT [ "entrypoint.sh" ] diff --git a/entrypoint.sh b/entrypoint.sh index eb6d63b2..02f07c79 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,40 +1,85 @@ #!/usr/bin/env sh set -e +echo "Starting entrypoint script..." + # Check if HOST_UID and HOST_GID are provided if [ -z "$HOST_UID" ]; then echo "ERROR: please set HOST_UID" >&2 exit 1 +else + echo "HOST_UID provided: $HOST_UID" fi if [ -z "$HOST_GID" ]; then echo "ERROR: please set HOST_GID" >&2 exit 1 +else + echo "HOST_GID provided: $HOST_GID" fi # Function to check if a group with the given GID already exists group_exists_with_gid() { getent group | cut -d: -f3 | grep -q "^$1$" + echo "Checking if group with GID $1 exists..." +} + +# Function to check if a user with the given UID already exists +user_exists_with_uid() { + getent passwd | cut -d: -f3 | grep -q "^$1$" + echo "Checking if user with UID $1 exists..." +} + +# Function to check if the scaf user already has the target UID +scaf_has_uid() { + [ "$(id -u scaf)" -eq "$1" ] + echo "Checking if scaf has UID $1..." +} + +# Function to check if the scaf group already has the target GID +scaf_has_gid() { + [ "$(getent group scaf | cut -d: -f3)" -eq "$1" ] + echo "Checking if scaf group has GID $1..." } # Modify the scaf user account to match the host user, adjusting for existing GID if group_exists_with_gid "$HOST_GID"; then - # Find the group name with the target GID - existing_group=$(getent group | awk -F: "\$3 == $HOST_GID { print \$1 }") - - # Use the existing group for the scaf user - usermod -g "$existing_group" scaf + echo "Group with GID $HOST_GID exists." + if ! scaf_has_gid "$HOST_GID"; then + existing_group=$(getent group | awk -F: "\$3 == $HOST_GID { print \$1 }") + echo "Existing group with GID $HOST_GID: $existing_group" + usermod -g "$existing_group" scaf + echo "Assigned existing group $existing_group to scaf." + else + echo "scaf already in the correct group." + fi else - # If GID does not exist, modify the scaf group to match HOST_GID + echo "Group with GID $HOST_GID does not exist, attempting to modify scaf group." groupmod -g "$HOST_GID" scaf + echo "Modified scaf group to GID $HOST_GID." +fi + +if ! scaf_has_uid "$HOST_UID"; then + if user_exists_with_uid "$HOST_UID"; then + echo "ERROR: UID '$HOST_UID' already exists" >&2 + exit 1 + else + echo "Modifying scaf UID to $HOST_UID." + usermod -u "$HOST_UID" scaf + echo "Modified scaf UID to $HOST_UID." + fi +else + echo "scaf already has the UID $HOST_UID." fi -# Modify the scaf user to match HOST_UID -usermod -u "$HOST_UID" scaf +chown scaf:scaf /home/scaf/out +echo "Finalizing: Dropping privileges and executing command..." # Drop privileges and execute the next container command, or 'sh' if not specified if [ "$#" -gt 0 ]; then + echo "Executing command: $@" su-exec scaf "$@" else + echo "No command specified, launching shell." su-exec scaf sh fi diff --git a/install.sh b/install.sh index f2d2ed1c..6a49df83 100755 --- a/install.sh +++ b/install.sh @@ -1,11 +1,12 @@ #!/bin/bash -SCAF_SCRIPT_URL="https://raw.githubusercontent.com/sixfeetup/scaf/main/scaf" +BRANCH=${SCAF_SCRIPT_BRANCH:-main} +SCAF_SCRIPT_URL="https://raw.githubusercontent.com/sixfeetup/scaf/${BRANCH}/scaf" TEMP_DOWNLOAD="./scaf" DESTINATION="/usr/local/bin/scaf" command_exists() { - command -v "$1" &> /dev/null + command -v "$1" > /dev/null 2>&1 } detect_os_and_arch() { @@ -81,7 +82,7 @@ install_tilt() { install_scaf() { # Download and install scaf - echo "Downloading scaf ..." + echo "Downloading scaf from $SCAF_SCRIPT_URL..." curl -L $SCAF_SCRIPT_URL -o $TEMP_DOWNLOAD if [ -f "$TEMP_DOWNLOAD" ]; then diff --git a/scaf b/scaf index c4a5812e..1591de64 100755 --- a/scaf +++ b/scaf @@ -1,19 +1,64 @@ #!/bin/bash -PROJECT_SLUG=${1:-myproject} +# Default repository URL if none is provided +DEFAULT_REPO_URL="https://github.com/sixfeetup/cookiecutter-sixiedjango/" +# Ensure at least one argument is provided (for project_slug) +if [ $# -lt 1 ]; then + echo "Usage: $0 project_slug [OPTIONS] [TEMPLATE]" + exit 1 +fi + +# The first argument is always the project slug +PROJECT_SLUG="$1" + +# Validate the project slug if ! [[ $PROJECT_SLUG =~ ^[a-zA-Z0-9]+$ ]]; then echo "Error: PROJECT_SLUG should only contain alphanumeric characters." exit 1 fi -docker run --rm -it -v .:/home/scaf/out \ +# Remove the project_slug from the argument list +shift + +# Assume the last argument is the template URL unless it starts with a dash +if [ $# -gt 0 ]; then + LAST_ARG="${@: -1}" + if [[ $LAST_ARG == -* ]]; then + REPO_URL="$DEFAULT_REPO_URL" + COOKIECUTTER_OPTIONS="$@" + else + REPO_URL="$LAST_ARG" + # Remove the last argument (the REPO_URL) from the options + COOKIECUTTER_OPTIONS="${@:1:$(($#-1))}" + fi +else + REPO_URL="$DEFAULT_REPO_URL" + COOKIECUTTER_OPTIONS="" +fi + +DOCKER_RUN_OPTIONS="" + +# Check if --no-input is in COOKIECUTTER_OPTIONS +if [[ "$COOKIECUTTER_OPTIONS" != *"--no-input"* ]]; then + DOCKER_RUN_OPTIONS="-it" +fi + +echo "DOCKER_RUN_OPTIONS: $DOCKER_RUN_OPTIONS" +echo "COOKIECUTTER_OPTIONS: $COOKIECUTTER_OPTIONS" +echo "REPO_URL: $REPO_URL" + +IMAGE_TAG=${IMAGE_TAG:-latest} +docker run --rm $DOCKER_RUN_OPTIONS -v "$(pwd):/home/scaf/out" \ -e HOST_UID="$(id -u)" \ -e HOST_GID="$(id -g)" \ - sixfeetup/scaf:latest \ - cookiecutter ${2:-https://github.com/sixfeetup/cookiecutter-sixiedjango/} \ - project_slug=$PROJECT_SLUG + sixfeetup/scaf:$IMAGE_TAG \ + cookiecutter \ + $COOKIECUTTER_OPTIONS \ + $REPO_URL \ + project_slug="$PROJECT_SLUG" +# Check if cookiecutter was successful if [ $? -eq 0 ]; then kind create cluster --name $PROJECT_SLUG else