Skip to content

Commit 5ee0538

Browse files
authored
🔀 Major Refactor of NetSuite CustomModules Template (PR #9)
🚀 Major Refactor of NetSuite CustomModules Template (PR #9) - 📘 Updated `readme.hbs` with an enhanced introduction section focusing on SuiteScript module testing and CI/CD integration, aligning with NS 2023.2 standards. - 🛠️ Added new scripts (`flattenObjectPath.sh`, `rmDependents.sh`, `web.config.private`) to improve project management and security. - 📚 Enhanced documentation generation process, integrating JSDoc comments and Markdown for automated class documentation. - 📈 Implemented CI/CD pipeline enhancements for various environments (production, multiple sandboxes) and refined Azure Pipeline configurations. - 🔒 Introduced `web.config.private` and `web.config.search.private` for enhanced security and UI functionality in the Documentation WebApp. - 🧪 Updated unit test configurations and mock setups to ensure comprehensive testing coverage and reliability. - 🐛 Fixed various issues in GitHub pipeline, including handling of existing directories and CSS file management. - 📄 Added detailed comments and structured organization to key configuration files (`manifest.tpl.xml`, `jsDocsConf.json`). - 🌟 General improvements for project clarity, efficiency, and compliance with the latest NetSuite standards. This PR represents a significant overhaul of the NetSuite CustomModules Template, ensuring a robust, efficient, and up-to-date development environment for SuiteScript projects.
2 parents 8fb2f43 + 5271449 commit 5ee0538

120 files changed

Lines changed: 32812 additions & 26785 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.ci/config/docsMD.config.min.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.ci/config/jest/modulePaths.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* @format
3+
* Custom Module Paths for Jest Testing in NetSuite SuiteCloud Projects
4+
*
5+
* Purpose:
6+
* This file defines a mapping between SuiteScript modules and their corresponding file paths
7+
* within the project structure. It is used in Jest testing to resolve SuiteScript module imports
8+
* that would otherwise not be recognized in the Jest environment.
9+
*
10+
* How It Works:
11+
* - Each object in the CustomModulePaths array represents a mapping between a SuiteScript module
12+
* (as used in NetSuite) and its equivalent local file path.
13+
* - 'module' key specifies the SuiteScript module path as it is referred to in the SuiteScript files.
14+
* - 'path' key provides the actual file path relative to the root directory of the project.
15+
* - This mapping allows Jest to correctly locate and import SuiteScript modules during tests.
16+
*
17+
* Integration with Jest:
18+
* - This mapping is imported into the Jest configuration (jest.config.js) under 'customStubs'.
19+
* - It enables Jest to understand and resolve the custom module paths specific to SuiteCloud projects,
20+
* facilitating the testing of SuiteScript modules with Jest.
21+
*
22+
* Example Format:
23+
* - Suppose a SuiteScript module is located at 'src/FileCabinet/SuiteScripts/Modules/aModule.js'
24+
* and is referred to in SuiteScripts as '/SuiteScripts/Modules/aModule'.
25+
* - The mapping object would be:
26+
* {
27+
* module: '/SuiteScripts/Modules/aModule',
28+
* path: '<rootDir>src/FileCabinet/SuiteScripts/Modules/aModule.js',
29+
* }
30+
* - This tells Jest that whenever '/SuiteScripts/Modules/aModule' is imported in a test,
31+
* it should actually load from the specified path in the project directory.
32+
*/
33+
34+
const CustomModulePaths = [
35+
{
36+
module: '/SuiteScripts/Modules/aModule',
37+
path: '<rootDir>src/FileCabinet/SuiteScripts/Modules/aModule',
38+
},
39+
{
40+
module: '/SuiteScripts/Modules/aModule.min',
41+
path: '<rootDir>src/FileCabinet/SuiteScripts/Modules/aModule.js',
42+
},
43+
{
44+
module: '/SuiteScripts/CS/customModule_CS',
45+
path: '<rootDir>src/FileCabinet/SuiteScripts/CS/customModule_CS',
46+
},
47+
{
48+
module: '/SuiteScripts/CS/customModule_CS.min',
49+
path: '<rootDir>src/FileCabinet/SuiteScripts/CS/customModule_CS.js',
50+
},
51+
];
52+
module.exports = {
53+
CustomModulePaths,
54+
};

.ci/config/jest/modulePaths.min.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.ci/config/jsDocsConf.json

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,41 @@
22
"source": {
33
"includePattern": ".+\\.js(doc|x)?$",
44
"include": ["."],
5-
"exclude": ["node_modules", "__tests__", "jest.config.js"],
5+
"exclude": ["node_modules", "docs"],
66
"excludePattern": ".+\\.min\\.js$"
77
},
88
"recurseDepth": 10,
99
"opts": {
10-
"destination": "./docs/",
11-
"recurse": true
10+
"readme": "./README.md",
11+
"destination": "./docs/private/",
12+
"recurse": true,
13+
"template": "node_modules/clean-jsdoc-theme",
14+
"theme_opts": {
15+
"title": "<a href=\"index.html\"><div class=\"sidebar-title\"><div class=\"image\"><img src=\"../assets/img/docs-icon.png\" \\></div><div class=\"text\">NetSuite Docs</div></div></a>",
16+
"homepageTitle": "NetSuite Project Documentation",
17+
"displayModuleHeader": true,
18+
"include_css": ["docs/assets/templates/jsDocStyle.css"],
19+
"codepen": {
20+
"enable_for": ["examples"],
21+
"options": {
22+
"js_external": "https://code.jquery.com/jquery-3.6.0.min.js",
23+
"js_pre_processor": "babel"
24+
}
25+
},
26+
"base_url": "http://localhost/private/",
27+
"favicon": "../assets/img/docs-icon.png",
28+
"search": true,
29+
"add_script_path": [
30+
{
31+
"src": "../assets/scripts/cs_sidebar.js",
32+
"defer": "defer"
33+
}
34+
]
35+
}
36+
},
37+
"plugins": ["plugins/markdown"],
38+
"markdown": {
39+
"hardwrap": false,
40+
"idInHeadings": true
1241
}
1342
}

.ci/scripts/createDeployment.sh

Lines changed: 79 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,126 @@
11
#!/bin/bash
2-
## Reset Manifest
3-
cp ./.ci/templates/manifest.tpl.xml src/manifest.xml
2+
# Script Usage: Test with `npm run generate-manifests --headbranch=production --sourcebranch=sandbox`
3+
4+
## Initial Checks and Setup
5+
### Checks if deploy.xml exists and exits if on a release run
6+
# deployFile: Flag to check existence of deploy.xml (0 = not exist, 1 = exist)
7+
# FLAT_OBJECTS: Flag to determine if flat object paths are used ("NO" by default)
8+
# GIT_BRANCHES: Specifies the range of branches to consider for deployment
9+
deployFile=0
10+
FLAT_OBJECTS="NO"
11+
GIT_BRANCHES="origin/$1..$2"
12+
13+
### Exit Logic for Existing deploy.xml on Release Run
14+
# Exits if deploy.xml exists and script is run for a release
15+
if test -f "src/deploy.xml"; then
16+
deployFile=1
17+
fi
18+
echo "Deploy: $3"
19+
if [[ $deployFile && $3 == "YES" ]]; then
20+
echo "File already created"
21+
cat "src/deploy.xml"
22+
exit 0
23+
fi
24+
25+
### Configuration for Object Directory and Repository Validation
26+
# Checks and sets flags based on script arguments for object directory usage and repo validation
27+
echo "Use Build Directory: $4"
28+
if [[ $4 == "YES" ]]; then
29+
FLAT_OBJECTS="YES"
30+
echo "Use flat Object paths on"
31+
fi
32+
echo "Running Validation: $5"
33+
if [[ $5 == "YES" ]]; then
34+
GIT_BRANCHES="origin/$1..origin/$2"
35+
echo "Validating Repo"
36+
fi
437

5-
## Store branch name for release
38+
## Manifest and Branch Setup
39+
### Resetting and Storing Manifest and Branch Information
40+
# Copies template manifest and stores the branch name for release
41+
cp ./.ci/templates/manifest.tpl.xml src/manifest.xml
642
echo "$2" >./.ci/.branch
743

8-
## Declare variables
9-
### Create xml schema variables
44+
## Variable Declaration
45+
### Defining Schema and Regex Patterns for Processing
46+
# Variables for XML schema and various regex patterns for file and object identification
1047
endOfLine="</path>\n"
11-
12-
### Create regex strings to test with
1348
srcRegex='src\/.*'
1449
attributesRegex='.*\.attributes.*'
1550
fileRegex='src\/FileCabinet\/SuiteScripts.*'
1651
objectRegex='src\/Objects\/.*'
1752
objectScriptPathRegex='.*scriptfile.*'
18-
19-
### Output strings for File and Object lines
20-
#### Add more here if using other branches of deploy.xml schema
2153
FILELINE=
2254
OBJECTLINE=
23-
## Read git log for files impacted since origin headbranch -- reverts are also in the log
55+
filePathRegex="\(.*\)/\(.*\)"
56+
57+
### Preparation for File and Object List Generation
58+
# Initializes the object file list for pipeline testing
59+
printf "" >objectFileList.pipeline-test.txt
60+
61+
## Git Log Processing
62+
### Reading Git Log to Identify Modified Files
63+
# Processes git log to update src files in the deployment, excluding certain file types
2464
while read line; do
25-
### We only want to update src files in deployment
65+
if [[ $line =~ \.(scss|sass|css)$ && $line != *.min.css ]]; then
66+
continue
67+
fi
2668
if [[ "$line" =~ $srcRegex ]]; then
27-
### Test if file exists, if not we can skip it and import as dependency later
28-
if ! test -f "$line"; then
69+
ADJUSTED_LINE="$line"
70+
if [[ "$line" =~ $objectRegex && $FLAT_OBJECTS == "YES" ]]; then
71+
fileName=$(echo "$line" | sed "s:$filePathRegex:\2:g")
72+
ADJUSTED_LINE="src/Objects/$fileName"
73+
fi
74+
echo "Evaluating: $ADJUSTED_LINE"
75+
if ! test -f "$ADJUSTED_LINE"; then
2976
continue
3077
fi
31-
32-
### Setup what the new line will look like
33-
newLine=$(echo "$line" | sed "s/src\//\t<path>~\//")"$endOfLine"
34-
35-
### Skip duplicates -- lines which are already prepped to go in to deploy.xml
78+
newLine=$(echo "$ADJUSTED_LINE" | sed "s/src\//\t<path>~\//")"$endOfLine"
3679
if [[ $OBJECTLINE == *"$newLine"* || $FILELINE == *"$newLine"* ]]; then
3780
continue
3881
fi
3982

40-
### Separate Files & Objects to build deploy.xml
41-
if [[ "$line" =~ $fileRegex ]]; then
42-
if [[ "$line" =~ $attributesRegex ]]; then
83+
### File and Object Separation for deploy.xml
84+
# Differentiates and processes files and objects for deployment
85+
if [[ "$ADJUSTED_LINE" =~ $fileRegex ]]; then
86+
if [[ "$ADJUSTED_LINE" =~ $attributesRegex ]]; then
4387
continue
4488
fi
45-
#### Is a file update
4689
FILELINE+="\t${newLine}"
47-
elif [[ "$line" =~ $objectRegex ]]; then
48-
### Test line to see if the object needs a file path dependency added
90+
elif [[ "$ADJUSTED_LINE" =~ $objectRegex ]]; then
4991
while read OBJLINE; do
5092
if [[ "$OBJLINE" =~ $objectScriptPathRegex ]]; then
51-
#### Modify line to deploy.xml schema
5293
SCRIPTPATH=$(echo "$OBJLINE" | sed "s/<scriptfile>\[/\/src/")
5394
SCRIPTPATH=$(echo "${SCRIPTPATH}" | sed "s/\]<\/scriptfile>//")
5495
depLine=$(echo "${SCRIPTPATH}" | sed "s/\/src\//\t<path>~\/FileCabinet\//")"$endOfLine"
5596
CLEANPATH=$(echo "$SCRIPTPATH" | sed "s/src\///")
5697
regexLineStr=".*$CLEANPATH"
57-
58-
#### Check if dependency file is already in file paths list
5998
if [[ "$FILELINE" =~ $regexLineStr ]]; then
6099
continue
61100
fi
62-
63-
##### Add to dependency to file list
64101
FILELINE+="\t${depLine}"
65102
fi
66-
done < <(cat "./${line}")
67-
68-
#### Is an object file update
103+
done < <(cat "./${ADJUSTED_LINE}")
104+
echo "${ADJUSTED_LINE}" >>objectFileList.pipeline-test.txt
69105
OBJECTLINE+="\t${newLine}"
70106
fi
71107
fi
72-
### Clear line variable
73108
line=""
74-
done < <(git log --oneline --stat origin/$1..$2 --name-only)
109+
done < <(git log --oneline --stat "$GIT_BRANCHES" --name-only)
75110

76-
## Generate deploy.xml file
77-
### Define output string variable
111+
## Deploy.xml Generation
112+
### Constructing deploy.xml Based on File and Object Modifications
113+
# Generates deploy.xml file with updated paths for files and objects based on git log
78114
OUTPUTLINES=""
79-
80-
### If file path entries is > 0 add files to deploy.xml
81115
if [[ $FILELINE ]]; then
116+
echo "##vso[task.setvariable variable=RELEASE_BUILD]true"
82117
OUTPUTLINES="<files>\n${FILELINE}\t</files>"
83118
fi
84-
85-
### If object path entries is > 0 add objects to deploy.xml
86119
if [[ $OBJECTLINE ]]; then
120+
echo "##vso[task.setvariable variable=RELEASE_BUILD]true"
87121
OUTPUTLINES="${OUTPUTLINES}\n\t<objects>\n${OBJECTLINE}\t</objects>"
88122
fi
89-
90-
### Print output to custom updated deploy.xml
91-
# shellcheck disable=SC2059
123+
echo "Writing Output"
92124
printf "<deploy>
93125
<configuration>
94126
<path>~/AccountConfiguration/*</path>
@@ -99,5 +131,7 @@ printf "<deploy>
99131
</translationimports>
100132
</deploy>" >src/deploy.xml
101133

102-
## Echo output for logging
134+
## Log Output
135+
### Displaying the Final deploy.xml for Verification
136+
# Outputs the final content of deploy.xml for logging and verification purposes
103137
cat src/deploy.xml
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
# Script Name: findMissingDependents.sh
3+
# Purpose:
4+
# This script is used to validate that NetSuite SuiteScript files in the repository
5+
# have corresponding SuiteCloud objects on the server. It's essential for ensuring
6+
# that all necessary script files are present and accounted for on the server.
7+
8+
# Usage: ./findMissingDependents.sh
9+
10+
# Functionality:
11+
# - The script reads a list of script IDs from a specified file (OBJFILE).
12+
# - For each script ID, it attempts to import the corresponding SuiteCloud object using the SuiteCloud CLI.
13+
# - If the import fails (indicating the SuiteCloud object is missing on the server),
14+
# the script logs the script ID to an error file (ERRORFILE).
15+
# - This process helps identify discrepancies between the repository and the server,
16+
# particularly missing SuiteCloud objects that may need attention.
17+
18+
# Example usage in package.json:
19+
# "find-missing-dependents": "bash .ci/scripts/findMissingDependents.sh"
20+
21+
SCRIPTIDREGEX="scriptid=\"(.*)\""
22+
SCRIPTIDSEDREGEX="\(.*\)scriptid=\"\(.*\)\"\(.*\)"
23+
OBJFILE="./deplist.rv-test.txt"
24+
DESTDIR="/Objects/_tmp/"
25+
FULLDESTDIR="./src/$DESTDIR"
26+
ERRORFILE="$FULLDESTDIR/errorList.txt"
27+
28+
mkdir $FULLDESTDIR
29+
echo "" >$ERRORFILE
30+
31+
while read line; do
32+
SCRIPTID=$line
33+
echo "Checking: $SCRIPTID"
34+
{
35+
npm run import-suitecloud-object --destinationfolder=$DESTDIR --scriptid=$SCRIPTID
36+
} || {
37+
echo "$line" >>$ERRORFILE
38+
}
39+
done < <(cat $OBJFILE)

.ci/scripts/flattenObjectPaths.sh

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/bin/bash
2+
3+
# This script is used by the "generate-manifests" script in the package.json file of 'netsuite-custommodules-template'.
4+
# It flattens the directory structure of NetSuite object files located in ./src/Objects/ and copies them to the build directory.
5+
# The script checks for changes in object files since a specified compare branch (usually 'origin/prod' or 'origin/main').
6+
7+
# Usage: ./flattenObjectPaths.sh [BUILD_DIRECTORY] [COMPARE_BRANCH]
8+
9+
# Parameters:
10+
# - BUILD_DIRECTORY: The destination directory where flattened object files will be copied.
11+
# - COMPARE_BRANCH: The branch to compare against to identify changed object files.
12+
13+
# The script iterates through all object files and compares their change history with the compare branch.
14+
# Only object files with changes will be copied to the build directory for deployment.
15+
# If a duplicate object name is detected, the script exits with an error to alert the user to investigate.
16+
17+
# Example usage in package.json:
18+
# "generate-manifests": "npm run compile-sass && bash .ci/scripts/createDeployment.sh $npm_config_headbranch $npm_config_sourcebranch $npm_config_releaserun $npm_config_flatobjects $npm_config_validaterun",
19+
# "flattenObjectPaths": "bash .ci/scripts/flattenObjectPaths.sh ./build/Objects origin/main origin/prod"
20+
21+
# This script is part of the automated deployment process for NetSuite SuiteCloud projects.
22+
23+
git fetch --all --prune
24+
25+
find ./src/Objects/ -type f \( -iname \*.xml \) | while read relativePath; do
26+
filePathRegex="\(.*\)/\(.*\)"
27+
fileName=$(echo "$relativePath" | sed "s:$filePathRegex:\2:g")
28+
squashedPathName="$1$fileName"
29+
30+
## This is where we test if there's a change to this object file.
31+
## Only objects with changes will be copied to the build directory for deployment.
32+
33+
## Read git log for files impacted since origin headbranch (reverts are also in the log).
34+
while read line; do
35+
changeLogFileName=$(echo "$line" | sed "s:$filePathRegex:\2:g")
36+
37+
### We only want to copy object files in deployment which have been changed.
38+
if [[ "$changeLogFileName" =~ $fileName ]]; then
39+
### Name matches change log, logic to copy file to build dir passes so far.
40+
## Test for duplicate objects and throw an exit error if a duplicate is located.
41+
if test -f "$squashedPathName"; then
42+
echo -e "\033[0;31mDUPLICATE_OBJECT_NAME_DETECTED: {squashedPathName: '$squashedPathName', relativePath:'$relativePath'}\033[0m"
43+
exit 1
44+
else
45+
echo "Copying $fileName"
46+
cp "$relativePath" "$1"
47+
fi
48+
break
49+
fi
50+
51+
### Clear line variable
52+
line=""
53+
54+
done < <(git log --oneline --stat "origin/$2..$3" --name-only "./src/Objects")
55+
done

.ci/scripts/minifyCSS.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
3+
# Loop through all SCSS files in the specified directory
4+
for input in src/FileCabinet/SuiteScripts/*.scss; do
5+
# Define the output file path by replacing the .scss extension with .min.css
6+
output="src/FileCabinet/SuiteScripts/$(basename "$input" .scss).min.css"
7+
8+
# Compile the SCSS file to minified CSS using node-sass
9+
node-sass --output-style compressed "$input" "$output"
10+
11+
# The resulting minified CSS is stored in the output file
12+
done

0 commit comments

Comments
 (0)