diff --git a/.gitpod.dockerfile b/.gitpod.dockerfile
deleted file mode 100644
index 6b680a1..0000000
--- a/.gitpod.dockerfile
+++ /dev/null
@@ -1,6 +0,0 @@
-FROM gitpod/workspace-full
-
-RUN sudo apt-get update \
- && sudo apt-get install -y doxygen \
- && sudo apt-get install -y graphviz \
- && sudo rm -rf /var/lib/apt/lists/*
diff --git a/.gitpod.yml b/.gitpod.yml
deleted file mode 100644
index b825a64..0000000
--- a/.gitpod.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-tasks:
- - init: npm install -g npm
- - command: npm i
- - command: npm i -g @sasjs/cli
-
-image:
- file: .gitpod.dockerfile
-vscode:
- extensions:
- - sasjs.sasjs-for-vscode
-
-github:
- prebuilds:
- # enable for the master/default branch (defaults to true)
- master: true
- # enable for all branches in this repo (defaults to false)
- branches: false
- # enable for pull requests coming from this repo (defaults to true)
- pullRequests: true
- # enable for pull requests coming from forks (defaults to false)
- pullRequestsFromForks: true
- # add a "Review in Gitpod" button as a comment to pull requests (defaults to true)
- addComment: true
- # add a "Review in Gitpod" button to pull requests (defaults to false)
- addBadge: false
- # add a label once the prebuild is ready to pull requests (defaults to false)
- addLabel: prebuilt-in-gitpod
diff --git a/.npmignore b/.npmignore
index 8ea87e4..c9a7666 100644
--- a/.npmignore
+++ b/.npmignore
@@ -1,6 +1,5 @@
all.sas
build.py
-.gitpod*
tests/
sasjs/
.github/
diff --git a/all.sas b/all.sas
index ae29d40..f008c4e 100644
--- a/all.sas
+++ b/all.sas
@@ -26428,6 +26428,7 @@ libname &libref1a JSON fileref=&fname1a;
/* %put Getting object uri from &libref1a..items; */
data _null_;
length contenttype name $1000;
+ call missing(of _all_);
set &libref1a..items;
if contenttype='jobDefinition' and upcase(name)="%upcase(&name)" then do;
call symputx('uri',cats("&base_uri",uri),'l');
@@ -30910,6 +30911,117 @@ endsub;
%end;
%mend mcf_string2file;/**
+ @file mx_createjob.sas
+ @brief Create a job in SAS 9, Viya or SASjs
+ @details Creates a Stored Process in SAS 9, a Job Execution Service in SAS
+ Viya, or a Stored Program on SASjs Server - depending on the executing
+ environment.
+
+Usage:
+
+ %* compile macros ;
+ filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
+ %inc mc;
+
+ %* write some code;
+ filename ft15f001 temp;
+ parmcards4;
+ data example1;
+ set sashelp.class;
+ run;
+ ;;;;
+
+ %* create the job;
+ %mx_createjob(path=/Public/app/jobs,name=myjob,replace=YES)
+
+
SAS Macros
+ @li mf_getplatform.sas
+ @li mm_createstp.sas
+ @li ms_createfile.sas
+ @li mv_createjob.sas
+
+ @param [in,out] path= The full folder path where the job will be created
+ @param [in,out] name= Job name. Avoid spaces.
+ @param [in] desc= The description of the job (optional)
+ @param [in] precode= Space separated list of filerefs, pointing to the code
+ that needs to be attached to the beginning of the job (optional)
+ @param [in] code= (ft15f001) Space seperated fileref(s) of the actual code to
+ be added
+ @param [in] replace= (YES) Select YES to replace any existing job in that
+ location
+ @param [in] mDebug= (0) set to 1 to show debug messages in the log
+
+ @author Allan Bowe
+
+ Related Macros
+ @li mx_createjob.test.sas
+ @li mx_createwebservice.sas
+
+**/
+
+%macro mx_createjob(path=HOME
+ ,name=initJob
+ ,precode=
+ ,code=ft15f001
+ ,desc=This job was created by the mx_createjob macro
+ ,replace=YES
+ ,mdebug=0
+)/*/STORE SOURCE*/;
+
+%if &syscc ge 4 %then %do;
+ %put syscc=&syscc - &sysmacroname will not execute in this state;
+ %return;
+%end;
+
+/* combine precode and code into a single file */
+%local tempref x fref freflist;
+%let tempref=%mf_getuniquefileref();
+%local work tmpfile;
+%let work=%sysfunc(pathname(work));
+%let tmpfile=&tempref..sas;
+filename &tempref "&work/&tmpfile";
+%let freflist=&precode &code ;
+%do x=1 %to %sysfunc(countw(&freflist));
+ %let fref=%scan(&freflist,&x);
+ %put &sysmacroname: adding &fref;
+ data _null_;
+ file &tempref lrecl=3000 termstr=crlf mod;
+ infile &fref lrecl=3000;
+ input;
+ put _infile_;
+ run;
+%end;
+
+%local platform; %let platform=%mf_getplatform();
+%if &platform=SASVIYA %then %do;
+ %if "&path"="HOME" %then %let path=/Users/&sysuserid/My Folder;
+ %mv_createjob(path=&path
+ ,name=&name
+ ,code=&tempref
+ ,desc=&desc
+ ,replace=&replace
+ )
+%end;
+%else %if &platform=SASJS %then %do;
+ %if "&path"="HOME" %then %let path=/Users/&_sasjs_username/My Folder;
+ %ms_createfile(&path/&name..sas
+ ,inref=&tempref
+ ,mdebug=&mdebug
+ )
+%end;
+%else %do;
+ %if "&path"="HOME" %then %let path=/User Folders/&_METAPERSON/My Folder;
+ %mm_createstp(stpname=&name
+ ,filename=&tmpfile
+ ,directory=&work
+ ,tree=&path
+ ,stpdesc=&desc
+ ,mDebug=&mdebug
+ )
+%end;
+filename &tempref clear;
+%mend mx_createjob;
+/**
@file mx_createwebservice.sas
@brief Create a web service in SAS 9, Viya or SASjs
@details Creates a SASJS ready Stored Process in SAS 9, a Job Execution
@@ -30959,6 +31071,9 @@ Usage:
@author Allan Bowe
+ Related Macros
+ @li mx_createjob.sas
+
**/
%macro mx_createwebservice(path=HOME
diff --git a/tests/x-platform/mx_createjob.test.sas b/tests/x-platform/mx_createjob.test.sas
new file mode 100644
index 0000000..5c958d8
--- /dev/null
+++ b/tests/x-platform/mx_createjob.test.sas
@@ -0,0 +1,304 @@
+/**
+ @file
+ @brief Testing mx_createjob.sas macro
+
+ Be sure to run %let mcTestAppLoc=/Public/temp/macrocore; when
+ running in Studio
+
+ SAS Macros
+ @li mx_createjob.sas
+ @li mp_assert.sas
+ @li mf_getuniquefileref.sas
+ @li mp_assertscope.sas
+
+**/
+
+/**
+ * Test 1 - Basic job creation with default parameters
+ * Also checking for scope leakage
+ */
+filename ft15f001 temp;
+parmcards4;
+ data example1;
+ set sashelp.class;
+ run;
+ %put Job executed successfully;
+;;;;
+%mp_assertscope(SNAPSHOT)
+%mx_createjob(path=&mcTestAppLoc/jobs,name=testjob1,replace=YES)
+%mp_assertscope(COMPARE)
+
+%mp_assert(
+ iftrue=(&syscc=0),
+ desc=Test 1: No errors after basic job creation,
+ outds=work.test_results
+)
+
+/**
+ * Test 2 - Job creation with custom description
+ */
+filename ft15f001 temp;
+parmcards4;
+ data example2;
+ set sashelp.cars;
+ run;
+;;;;
+%mx_createjob(
+ path=&mcTestAppLoc/jobs,
+ name=testjob2,
+ desc=Custom job description for testing,
+ replace=YES
+)
+
+%mp_assert(
+ iftrue=(&syscc=0),
+ desc=Test 2: Job created with custom description,
+ outds=work.test_results
+)
+
+/**
+ * Test 3 - Job creation with precode
+ */
+filename precode1 temp;
+data _null_;
+ file precode1;
+ put '%let testvar=PreCodeValue;';
+ put '%put &=testvar;';
+run;
+
+filename ft15f001 temp;
+parmcards4;
+ data example3;
+ set sashelp.class;
+ precode_var="&testvar";
+ run;
+;;;;
+%mx_createjob(
+ path=&mcTestAppLoc/jobs,
+ name=testjob3,
+ precode=precode1,
+ replace=YES
+)
+
+%mp_assert(
+ iftrue=(&syscc=0),
+ desc=Test 3: Job created with precode parameter,
+ outds=work.test_results
+)
+
+filename precode1 clear;
+
+/**
+ * Test 4 - Job creation with multiple code filerefs
+ */
+%let code1=%mf_getuniquefileref();
+%let code2=%mf_getuniquefileref();
+
+filename &code1 temp;
+data _null_;
+ file &code1;
+ put 'data work.part1;';
+ put ' set sashelp.class(obs=5);';
+ put 'run;';
+run;
+
+filename &code2 temp;
+data _null_;
+ file &code2;
+ put 'data work.part2;';
+ put ' set sashelp.class(firstobs=6);';
+ put 'run;';
+run;
+
+%mx_createjob(
+ path=&mcTestAppLoc/jobs,
+ name=testjob4,
+ code=&code1 &code2,
+ replace=YES
+)
+
+%mp_assert(
+ iftrue=(&syscc=0),
+ desc=Test 4: Job created with multiple code filerefs,
+ outds=work.test_results
+)
+
+filename &code1 clear;
+filename &code2 clear;
+
+/**
+ * Test 5 - Job creation with both precode and multiple code files
+ */
+%let pre1=%mf_getuniquefileref();
+%let pre2=%mf_getuniquefileref();
+%let main1=%mf_getuniquefileref();
+
+filename &pre1 temp;
+data _null_;
+ file &pre1;
+ put '%let globalvar1=Value1;';
+run;
+
+filename &pre2 temp;
+data _null_;
+ file &pre2;
+ put '%let globalvar2=Value2;';
+run;
+
+filename &main1 temp;
+data _null_;
+ file &main1;
+ put 'data work.combined;';
+ put ' var1="&globalvar1";';
+ put ' var2="&globalvar2";';
+ put ' output;';
+ put 'run;';
+run;
+
+%mx_createjob(
+ path=&mcTestAppLoc/jobs,
+ name=testjob5,
+ precode=&pre1 &pre2,
+ code=&main1,
+ desc=Job with multiple precode and code files,
+ replace=YES
+)
+
+%mp_assert(
+ iftrue=(&syscc=0),
+ desc=Test 5: Job created with multiple precode and code files,
+ outds=work.test_results
+)
+
+filename &pre1 clear;
+filename &pre2 clear;
+filename &main1 clear;
+
+/**
+ * Test 6 - Job creation with special characters in code
+ */
+filename ft15f001 temp;
+parmcards4;
+ data example6;
+ length text $200;
+ text='Special chars: & % $ # @ !';
+ output;
+ text="Quotes: 'single' and ""double""";
+ output;
+ run;
+ %put Test with special characters;
+;;;;
+%mx_createjob(
+ path=&mcTestAppLoc/jobs,
+ name=testjob6,
+ desc=Job with special characters in code,
+ replace=YES
+)
+
+%mp_assert(
+ iftrue=(&syscc=0),
+ desc=Test 6: Job created with special characters in code,
+ outds=work.test_results
+)
+
+/**
+ * Test 7 - Job creation with macro code
+ */
+filename ft15f001 temp;
+parmcards4;
+ %macro testmacro();
+ data example7;
+ set sashelp.class;
+ where age > 12;
+ run;
+ %mend testmacro;
+
+ %testmacro()
+;;;;
+%mx_createjob(
+ path=&mcTestAppLoc/jobs,
+ name=testjob7,
+ desc=Job containing macro definitions,
+ replace=YES
+)
+
+%mp_assert(
+ iftrue=(&syscc=0),
+ desc=Test 7: Job created with macro code,
+ outds=work.test_results
+)
+
+/**
+ * Test 8 - Job creation with empty code (edge case)
+ */
+filename ft15f001 temp;
+data _null_;
+ file ft15f001;
+ put '/* Empty job for testing */';
+run;
+
+%mx_createjob(
+ path=&mcTestAppLoc/jobs,
+ name=testjob8,
+ desc=Job with minimal code,
+ replace=YES
+)
+
+%mp_assert(
+ iftrue=(&syscc=0),
+ desc=Test 8: Job created with minimal code,
+ outds=work.test_results
+)
+
+/**
+ * Test 9 - Job creation with long code block
+ */
+filename ft15f001 temp;
+data _null_;
+ file ft15f001;
+ put 'data work.longtest;';
+ do i=1 to 50;
+ put ' var' i +(-1) '=' i ';';
+ end;
+ put ' output;';
+ put 'run;';
+run;
+
+%mx_createjob(
+ path=&mcTestAppLoc/jobs,
+ name=testjob9,
+ desc=Job with many variables,
+ replace=YES
+)
+
+%mp_assert(
+ iftrue=(&syscc=0),
+ desc=Test 9: Job created with long code block,
+ outds=work.test_results
+)
+
+/**
+ * Test 10 - Replace existing job (replace=YES)
+ */
+filename ft15f001 temp;
+parmcards4;
+ data example10_v1;
+ set sashelp.class;
+ run;
+;;;;
+%mx_createjob(path=&mcTestAppLoc/jobs,name=testjob10,replace=YES)
+
+/* Now replace it */
+filename ft15f001 temp;
+parmcards4;
+ data example10_v2;
+ set sashelp.cars;
+ run;
+;;;;
+%mx_createjob(path=&mcTestAppLoc/jobs,name=testjob10,replace=YES)
+
+%mp_assert(
+ iftrue=(&syscc=0),
+ desc=Test 10: Job replaced successfully with replace=YES,
+ outds=work.test_results
+)
diff --git a/viya/mv_deletejes.sas b/viya/mv_deletejes.sas
index 27532a4..994ce93 100644
--- a/viya/mv_deletejes.sas
+++ b/viya/mv_deletejes.sas
@@ -118,6 +118,7 @@ libname &libref1a JSON fileref=&fname1a;
/* %put Getting object uri from &libref1a..items; */
data _null_;
length contenttype name $1000;
+ call missing(of _all_);
set &libref1a..items;
if contenttype='jobDefinition' and upcase(name)="%upcase(&name)" then do;
call symputx('uri',cats("&base_uri",uri),'l');
diff --git a/xplatform/mx_createjob.sas b/xplatform/mx_createjob.sas
new file mode 100644
index 0000000..d4b10a5
--- /dev/null
+++ b/xplatform/mx_createjob.sas
@@ -0,0 +1,111 @@
+/**
+ @file mx_createjob.sas
+ @brief Create a job in SAS 9, Viya or SASjs
+ @details Creates a Stored Process in SAS 9, a Job Execution Service in SAS
+ Viya, or a Stored Program on SASjs Server - depending on the executing
+ environment.
+
+Usage:
+
+ %* compile macros ;
+ filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
+ %inc mc;
+
+ %* write some code;
+ filename ft15f001 temp;
+ parmcards4;
+ data example1;
+ set sashelp.class;
+ run;
+ ;;;;
+
+ %* create the job;
+ %mx_createjob(path=/Public/app/jobs,name=myjob,replace=YES)
+
+ SAS Macros
+ @li mf_getplatform.sas
+ @li mm_createstp.sas
+ @li ms_createfile.sas
+ @li mv_createjob.sas
+
+ @param [in,out] path= The full folder path where the job will be created
+ @param [in,out] name= Job name. Avoid spaces.
+ @param [in] desc= The description of the job (optional)
+ @param [in] precode= Space separated list of filerefs, pointing to the code
+ that needs to be attached to the beginning of the job (optional)
+ @param [in] code= (ft15f001) Space seperated fileref(s) of the actual code to
+ be added
+ @param [in] replace= (YES) Select YES to replace any existing job in that
+ location
+ @param [in] mDebug= (0) set to 1 to show debug messages in the log
+
+ @author Allan Bowe
+
+ Related Macros
+ @li mx_createjob.test.sas
+ @li mx_createwebservice.sas
+
+**/
+
+%macro mx_createjob(path=HOME
+ ,name=initJob
+ ,precode=
+ ,code=ft15f001
+ ,desc=This job was created by the mx_createjob macro
+ ,replace=YES
+ ,mdebug=0
+)/*/STORE SOURCE*/;
+
+%if &syscc ge 4 %then %do;
+ %put syscc=&syscc - &sysmacroname will not execute in this state;
+ %return;
+%end;
+
+/* combine precode and code into a single file */
+%local tempref x fref freflist;
+%let tempref=%mf_getuniquefileref();
+%local work tmpfile;
+%let work=%sysfunc(pathname(work));
+%let tmpfile=&tempref..sas;
+filename &tempref "&work/&tmpfile";
+%let freflist=&precode &code ;
+%do x=1 %to %sysfunc(countw(&freflist));
+ %let fref=%scan(&freflist,&x);
+ %put &sysmacroname: adding &fref;
+ data _null_;
+ file &tempref lrecl=3000 termstr=crlf mod;
+ infile &fref lrecl=3000;
+ input;
+ put _infile_;
+ run;
+%end;
+
+%local platform; %let platform=%mf_getplatform();
+%if &platform=SASVIYA %then %do;
+ %if "&path"="HOME" %then %let path=/Users/&sysuserid/My Folder;
+ %mv_createjob(path=&path
+ ,name=&name
+ ,code=&tempref
+ ,desc=&desc
+ ,replace=&replace
+ )
+%end;
+%else %if &platform=SASJS %then %do;
+ %if "&path"="HOME" %then %let path=/Users/&_sasjs_username/My Folder;
+ %ms_createfile(&path/&name..sas
+ ,inref=&tempref
+ ,mdebug=&mdebug
+ )
+%end;
+%else %do;
+ %if "&path"="HOME" %then %let path=/User Folders/&_METAPERSON/My Folder;
+ %mm_createstp(stpname=&name
+ ,filename=&tmpfile
+ ,directory=&work
+ ,tree=&path
+ ,stpdesc=&desc
+ ,mDebug=&mdebug
+ )
+%end;
+filename &tempref clear;
+%mend mx_createjob;
diff --git a/xplatform/mx_createwebservice.sas b/xplatform/mx_createwebservice.sas
index 8e41978..ff2e1ac 100644
--- a/xplatform/mx_createwebservice.sas
+++ b/xplatform/mx_createwebservice.sas
@@ -48,6 +48,9 @@ Usage:
@author Allan Bowe
+ Related Macros
+ @li mx_createjob.sas
+
**/
%macro mx_createwebservice(path=HOME