From 690880faa4076d043ead1c7ebb237767fb2c4f93 Mon Sep 17 00:00:00 2001 From: Twirre Meulenbelt <43213592+TwirreM@users.noreply.github.com> Date: Tue, 25 Nov 2025 10:55:57 +0100 Subject: [PATCH 1/6] feat: send program to backend in the latest form ref: N25B-198 --- src/pages/VisProgPage/VisProg.tsx | 15 +++++++++-- .../visualProgrammingUI/nodes/TriggerNode.tsx | 26 +++++++++++++------ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/pages/VisProgPage/VisProg.tsx b/src/pages/VisProgPage/VisProg.tsx index c579c6c..54ad43c 100644 --- a/src/pages/VisProgPage/VisProg.tsx +++ b/src/pages/VisProgPage/VisProg.tsx @@ -109,9 +109,20 @@ function VisualProgrammingUI() { // currently outputs the prepared program to the console function runProgram() { - const program = graphReducer(); - console.log(program); + const phases = graphReducer(); + const program = {phases} console.log(JSON.stringify(program, null, 2)); + fetch( + "http://localhost:8000/program", + { + method: "POST", + headers: {"Content-Type": "application/json"}, + body: JSON.stringify(program), + } + ).then((res) => { + if (!res.ok) throw new Error("Failed communicating with the backend.") + console.log("Successfully sent the program to the backend."); + }).catch(() => console.log("Failed to send program to the backend.")); } /** diff --git a/src/pages/VisProgPage/visualProgrammingUI/nodes/TriggerNode.tsx b/src/pages/VisProgPage/visualProgrammingUI/nodes/TriggerNode.tsx index a6f114e..e60d954 100644 --- a/src/pages/VisProgPage/visualProgrammingUI/nodes/TriggerNode.tsx +++ b/src/pages/VisProgPage/visualProgrammingUI/nodes/TriggerNode.tsx @@ -67,19 +67,29 @@ export default function TriggerNode(props: NodeProps) { /** * Reduces each Trigger, including its children down into its relevant data. - * @param node: The Node Properties of this node. - * @param nodes: all the nodes in the graph. + * @param node The Node Properties of this node. + * @param nodes all the nodes in the graph. */ -export function TriggerReduce(node: Node, nodes: Node[]) { +export function TriggerReduce(node: TriggerNode, nodes: Node[]) { // Replace this for nodes functionality if (nodes.length <= -1) { console.warn("Impossible nodes length in TriggerReduce") } - const data = node.data as TriggerNodeData; - return { - label: data.label, - list: data.triggers, - } + const data = node.data; + switch (data.triggerType) { + case "keywords": + return { + id: node.id, + type: "keywords", + label: data.label, + keywords: data.triggers, + }; + default: + return { + ...data, + id: node.id, + }; + } } /** From 32c8c985c3edf7309842345352a018a795c1e880 Mon Sep 17 00:00:00 2001 From: Twirre Meulenbelt <43213592+TwirreM@users.noreply.github.com> Date: Tue, 25 Nov 2025 11:06:11 +0100 Subject: [PATCH 2/6] chore: more general type required --- src/pages/VisProgPage/visualProgrammingUI/nodes/TriggerNode.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/VisProgPage/visualProgrammingUI/nodes/TriggerNode.tsx b/src/pages/VisProgPage/visualProgrammingUI/nodes/TriggerNode.tsx index e60d954..cfeac8c 100644 --- a/src/pages/VisProgPage/visualProgrammingUI/nodes/TriggerNode.tsx +++ b/src/pages/VisProgPage/visualProgrammingUI/nodes/TriggerNode.tsx @@ -70,7 +70,7 @@ export default function TriggerNode(props: NodeProps) { * @param node The Node Properties of this node. * @param nodes all the nodes in the graph. */ -export function TriggerReduce(node: TriggerNode, nodes: Node[]) { +export function TriggerReduce(node: Node, nodes: Node[]) { // Replace this for nodes functionality if (nodes.length <= -1) { console.warn("Impossible nodes length in TriggerReduce") From 3d7997e8d04796fecffb3d5a43338e1e9f9e26ee Mon Sep 17 00:00:00 2001 From: Twirre Meulenbelt <43213592+TwirreM@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:02:48 +0100 Subject: [PATCH 3/6] feat: introduce git hooks Make installing git hooks easy using Husky. Also, updating the commit message checks. Includes setup instructions in the README. ref: N25B-366 --- .githooks/check-branch-name.sh | 77 ++++++++++++++++++ .githooks/check-commit-msg.sh | 138 +++++++++++++++++++++++++++++++++ .githooks/commit-msg | 16 ---- .githooks/pre-commit | 17 ---- .githooks/prepare-commit-msg | 9 --- .husky/commit-msg | 1 + .husky/pre-commit | 3 + README.md | 19 +++-- package-lock.json | 17 ++++ package.json | 6 +- 10 files changed, 251 insertions(+), 52 deletions(-) create mode 100755 .githooks/check-branch-name.sh create mode 100755 .githooks/check-commit-msg.sh delete mode 100755 .githooks/commit-msg delete mode 100755 .githooks/pre-commit delete mode 100755 .githooks/prepare-commit-msg create mode 100644 .husky/commit-msg create mode 100644 .husky/pre-commit diff --git a/.githooks/check-branch-name.sh b/.githooks/check-branch-name.sh new file mode 100755 index 0000000..6a6669a --- /dev/null +++ b/.githooks/check-branch-name.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +# This script checks if the current branch name follows the specified format. +# It's designed to be used as a 'pre-commit' git hook. + +# Format: / +# Example: feat/add-user-login + +# --- Configuration --- +# An array of allowed commit types +ALLOWED_TYPES=(feat fix refactor perf style test docs build chore revert) +# An array of branches to ignore +IGNORED_BRANCHES=(main dev demo) + +# --- Colors for Output --- +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# --- Helper Functions --- +error_exit() { + echo -e "${RED}ERROR: $1${NC}" >&2 + echo -e "${YELLOW}Branch name format is incorrect. Aborting commit.${NC}" >&2 + exit 1 +} + +# --- Main Logic --- + +# 1. Get the current branch name +BRANCH_NAME=$(git symbolic-ref --short HEAD) + +# 2. Check if the current branch is in the ignored list +for ignored_branch in "${IGNORED_BRANCHES[@]}"; do + if [ "$BRANCH_NAME" == "$ignored_branch" ]; then + echo -e "${GREEN}Branch check skipped for default branch: $BRANCH_NAME${NC}" + exit 0 + fi +done + +# 3. Validate the overall structure: / +if ! [[ "$BRANCH_NAME" =~ ^[a-z]+/.+$ ]]; then + error_exit "Branch name must be in the format: /\nExample: feat/add-user-login" +fi + +# 4. Extract the type and description +TYPE=$(echo "$BRANCH_NAME" | cut -d'/' -f1) +DESCRIPTION=$(echo "$BRANCH_NAME" | cut -d'/' -f2-) + +# 5. Validate the +type_valid=false +for allowed_type in "${ALLOWED_TYPES[@]}"; do + if [ "$TYPE" == "$allowed_type" ]; then + type_valid=true + break + fi +done + +if [ "$type_valid" == false ]; then + error_exit "Invalid type '$TYPE'.\nAllowed types are: ${ALLOWED_TYPES[*]}" +fi + +# 6. Validate the +# Regex breakdown: +# ^[a-z0-9]+ - Starts with one or more lowercase letters/numbers (the first word). +# (-[a-z0-9]+){0,5} - Followed by a group of (dash + word) 0 to 5 times. +# $ - End of the string. +# This entire pattern enforces 1 to 6 words total, separated by dashes. +DESCRIPTION_REGEX="^[a-z0-9]+(-[a-z0-9]+){0,5}$" + +if ! [[ "$DESCRIPTION" =~ $DESCRIPTION_REGEX ]]; then + error_exit "Invalid short description '$DESCRIPTION'.\nIt must be a maximum of 6 words, all lowercase, separated by dashes.\nExample: add-new-user-authentication-feature" +fi + +# If all checks pass, exit successfully +echo -e "${GREEN}Branch name '$BRANCH_NAME' is valid.${NC}" +exit 0 diff --git a/.githooks/check-commit-msg.sh b/.githooks/check-commit-msg.sh new file mode 100755 index 0000000..2dd592c --- /dev/null +++ b/.githooks/check-commit-msg.sh @@ -0,0 +1,138 @@ +#!/usr/bin/env bash + +# This script checks if a commit message follows the specified format. +# It's designed to be used as a 'commit-msg' git hook. + +# Format: +# : +# +# [optional] +# +# [ref/close]: + +# --- Configuration --- +# An array of allowed commit types +ALLOWED_TYPES=(feat fix refactor perf style test docs build chore revert) + +# --- Colors for Output --- +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# The first argument to the hook is the path to the file containing the commit message +COMMIT_MSG_FILE=$1 + +# --- Automated Commit Detection --- + +# Read the first line (header) for initial checks +HEADER=$(head -n 1 "$COMMIT_MSG_FILE") + +echo 'Given commit message:' +echo $HEADER + +# Check for Merge commits (covers 'git merge' and PR merges from GitHub/GitLab) +# Examples: "Merge branch 'main' into ...", "Merge pull request #123 from ..." +MERGE_PATTERN="^Merge (remote-tracking )?(branch|pull request|tag) .*" +if [[ "$HEADER" =~ $MERGE_PATTERN ]]; then + echo -e "${GREEN}Merge commit detected by message content. Skipping validation.${NC}" + exit 0 +fi + +# Check for Revert commits +# Example: "Revert "feat: add new feature"" +REVERT_PATTERN="^Revert \".*\"" +if [[ "$HEADER" =~ $REVERT_PATTERN ]]; then + echo -e "${GREEN}Revert commit detected by message content. Skipping validation.${NC}" + exit 0 +fi + +# Check for Cherry-pick commits (this pattern appears at the end of the message) +# Example: "(cherry picked from commit deadbeef...)" +# We use grep -q to search the whole file quietly. +CHERRY_PICK_PATTERN="\(cherry picked from commit [a-f0-9]{7,40}\)" +if grep -qE "$CHERRY_PICK_PATTERN" "$COMMIT_MSG_FILE"; then + echo -e "${GREEN}Cherry-pick detected by message content. Skipping validation.${NC}" + exit 0 +fi + +# Check for Squash +# Example: "Squash commits ..." +SQUASH_PATTERN="^Squash .+" +if [[ "$HEADER" =~ $SQUASH_PATTERN ]]; then + echo -e "${GREEN}Squash commit detected by message content. Skipping validation.${NC}" + exit 0 +fi + +# --- Validation Functions --- + +# Function to print an error message and exit +# Usage: error_exit "Your error message here" +error_exit() { + # >&2 redirects echo to stderr + echo -e "${RED}ERROR: $1${NC}" >&2 + echo -e "${YELLOW}Commit message format is incorrect. Aborting commit.${NC}" >&2 + exit 1 +} + +# --- Main Logic --- + +# 1. Read the header (first line) of the commit message +HEADER=$(head -n 1 "$COMMIT_MSG_FILE") + +# 2. Validate the header format: : +# Regex breakdown: +# ^(type1|type2|...) - Starts with one of the allowed types +# : - Followed by a literal colon +# \s - Followed by a single space +# .+ - Followed by one or more characters for the description +# $ - End of the line +TYPES_REGEX=$( + IFS="|" + echo "${ALLOWED_TYPES[*]}" +) +HEADER_REGEX="^($TYPES_REGEX): .+$" + +if ! [[ "$HEADER" =~ $HEADER_REGEX ]]; then + error_exit "Invalid header format.\n\nHeader must be in the format: : \nAllowed types: ${ALLOWED_TYPES[*]}\nExample: feat: add new user authentication feature" +fi + +# Only validate footer if commit type is not chore +TYPE=$(echo "$HEADER" | cut -d':' -f1) +if [ "$TYPE" != "chore" ]; then + # 3. Validate the footer (last line) of the commit message + FOOTER=$(tail -n 1 "$COMMIT_MSG_FILE") + + # Regex breakdown: + # ^(ref|close) - Starts with 'ref' or 'close' + # : - Followed by a literal colon + # \s - Followed by a single space + # N25B- - Followed by the literal string 'N25B-' + # [0-9]+ - Followed by one or more digits + # $ - End of the line + FOOTER_REGEX="^(ref|close): N25B-[0-9]+$" + + if ! [[ "$FOOTER" =~ $FOOTER_REGEX ]]; then + error_exit "Invalid footer format.\n\nFooter must be in the format: [ref/close]: \nExample: ref: N25B-123" + fi +fi + +# 4. If the message has more than 2 lines, validate the separator +# A blank line must exist between the header and the body. +LINE_COUNT=$(wc -l <"$COMMIT_MSG_FILE" | xargs) # xargs trims whitespace + +# We only care if there is a body. Header + Footer = 2 lines. +# Header + Blank Line + Body... + Footer > 2 lines. +if [ "$LINE_COUNT" -gt 2 ]; then + # Get the second line + SECOND_LINE=$(sed -n '2p' "$COMMIT_MSG_FILE") + + # Check if the second line is NOT empty. If it's not, it's an error. + if [ -n "$SECOND_LINE" ]; then + error_exit "Missing blank line between header and body.\n\nThe second line of your commit message must be empty if a body is present." + fi +fi + +# If all checks pass, exit with success +echo -e "${GREEN}Commit message is valid.${NC}" +exit 0 diff --git a/.githooks/commit-msg b/.githooks/commit-msg deleted file mode 100755 index 41992ad..0000000 --- a/.githooks/commit-msg +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -commit_msg_file=$1 -commit_msg=$(cat "$commit_msg_file") - -if echo "$commit_msg" | grep -Eq "^(feat|fix|refactor|perf|style|test|docs|build|chore|revert): .+"; then - if echo "$commit_msg" | grep -Eq "^(ref|close):\sN25B-.+"; then - exit 0 - else - echo "❌ Commit message invalid! Must end with [ref/close]: N25B-000" - exit 1 - fi -else - echo "❌ Commit message invalid! Must start with : " - exit 1 -fi \ No newline at end of file diff --git a/.githooks/pre-commit b/.githooks/pre-commit deleted file mode 100755 index 7e94937..0000000 --- a/.githooks/pre-commit +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -# Get current branch -branch=$(git rev-parse --abbrev-ref HEAD) - -if echo "$branch" | grep -Eq "(dev|main)"; then - echo 0 -fi - -# allowed pattern -if echo "$branch" | grep -Eq "^(feat|fix|refactor|perf|style|test|docs|build|chore|revert)\/\w+(-\w+){0,5}$"; then - exit 0 -else - echo "❌ Invalid branch name: $branch" - echo "Branch must be named / (must have one to six words separated by a dash)" - exit 1 -fi \ No newline at end of file diff --git a/.githooks/prepare-commit-msg b/.githooks/prepare-commit-msg deleted file mode 100755 index 5b706c1..0000000 --- a/.githooks/prepare-commit-msg +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -echo "#: - -#[optional body] - -#[optional footer(s)] - -#[ref/close]: " > $1 \ No newline at end of file diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..297870d --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1 @@ +sh .githooks/check-commit-msg.sh $1 diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..822552c --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,3 @@ +sh .githooks/check-branch-name.sh + +npm run lint diff --git a/README.md b/README.md index 9d8fee2..47e2054 100644 --- a/README.md +++ b/README.md @@ -28,18 +28,21 @@ npm run dev It should automatically reload when you save changes. -## GitHooks +## Git Hooks -To activate automatic commits/branch name checks run: +To activate automatic linting, branch name checks and commit message checks, run: -```shell -git config --local core.hooksPath .githooks +```bash +npm run prepare ``` -If your commit fails its either: -branch name != /description-of-branch , -commit name != : description of the commit. - : N25B-Num's +You might get an error along the lines of `Can't install pre-commit with core.hooksPath` set. To fix this, simply unset the hooksPath by running: + +```bash +git config --local --unset core.hooksPath +``` + +Then run the pre-commit install commands again. ## Documentation diff --git a/package-lock.json b/package-lock.json index 395326d..b225239 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "globals": "^16.4.0", + "husky": "^9.1.7", "identity-obj-proxy": "^3.0.0", "jest": "^30.2.0", "jest-environment-jsdom": "^30.2.0", @@ -5051,6 +5052,22 @@ "node": ">=10.17.0" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", diff --git a/package.json b/package.json index a493ed2..6e7ea28 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,9 @@ "scripts": { "dev": "vite", "build": "tsc -b && vite build", - "lint": "eslint .", - "preview": "vite preview" + "lint": "eslint src test", + "preview": "vite preview", + "prepare": "husky" }, "dependencies": { "@neodrag/react": "^2.3.1", @@ -30,6 +31,7 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "globals": "^16.4.0", + "husky": "^9.1.7", "identity-obj-proxy": "^3.0.0", "jest": "^30.2.0", "jest-environment-jsdom": "^30.2.0", From 7d3c63630a091d0d4b6bd79607ef74b1777edb3b Mon Sep 17 00:00:00 2001 From: Twirre Meulenbelt <43213592+TwirreM@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:06:14 +0100 Subject: [PATCH 4/6] feat: introduce CI/CD runner Installs dependencies, checks style, runs tests. ref: N25B-366 --- .gitlab-ci.yml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..46727b7 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,40 @@ +# ---------- GLOBAL SETUP ---------- # +workflow: + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + +stages: + - install + - lint + - test + +variables: + NODE_VERSION: "24.11.1" + BASE_LAYER: trixie-slim + +default: + image: docker.io/library/node:${NODE_VERSION}-${BASE_LAYER} + +# --------- INSTALLING --------- # +install: + stage: install + tags: + - install + script: + - npm ci + +# ---------- LINTING ---------- # +lint: + stage: lint + tags: + - lint + script: + - npm run lint + +# ---------- TESTING ---------- # +test: + stage: test + tags: + - test + script: + - npm run test From ea85a05f273c9749c144c430a0644f195f5a2ff5 Mon Sep 17 00:00:00 2001 From: Twirre Meulenbelt <43213592+TwirreM@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:42:00 +0100 Subject: [PATCH 5/6] fix: use install artifacts Uses install artifacts in later stages. ref: N25B-366 --- .gitlab-ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 46727b7..371c0a9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,6 +14,11 @@ variables: default: image: docker.io/library/node:${NODE_VERSION}-${BASE_LAYER} + cache: + key: "${CI_COMMIT_REF_SLUG}" + paths: + - node_modules/ + policy: pull-push # --------- INSTALLING --------- # install: @@ -22,10 +27,16 @@ install: - install script: - npm ci + artifacts: + paths: + - node_modules/ + expire_in: 1h # ---------- LINTING ---------- # lint: stage: lint + needs: + - install tags: - lint script: @@ -34,6 +45,8 @@ lint: # ---------- TESTING ---------- # test: stage: test + needs: + - install tags: - test script: From e680ad3195d0469ea10c076199f3e5b9df52dd21 Mon Sep 17 00:00:00 2001 From: Twirre Meulenbelt <43213592+TwirreM@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:46:56 +0100 Subject: [PATCH 6/6] fix: add `test` script to package.json ref: N25B-366 --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 6e7ea28..cd08dca 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "build": "tsc -b && vite build", "lint": "eslint src test", "preview": "vite preview", + "test": "jest", "prepare": "husky" }, "dependencies": {