Skip to content

Commit

Permalink
Merge pull request #317 from sasjs/gitfuncs
Browse files Browse the repository at this point in the history
feat: two new macros (mp_gitadd and mp_gitstatus) with corresponding …
  • Loading branch information
allanbowe authored Oct 20, 2022
2 parents 6f8ec5d + f37c2e5 commit f832e93
Show file tree
Hide file tree
Showing 7 changed files with 450 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,10 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: SAS Packages Release
run: |
sasjs compile job -s sasjs/utils/create_sas_package.sas -o sasjsbuild/makepak.sas
# this part depends on https://github.com/sasjs/server/issues/307
# sasjs run sasjsbuild/makepak.sas -t sas9
46 changes: 46 additions & 0 deletions base/mp_gitadd.sas
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
@file
@brief Stages files in a GIT repo
@details Uses the output dataset from mp_gitstatus.sas to determine the files
that should be staged.
If STAGED != `"TRUE"` then the file is staged (so you could provide an empty
char column if staging all observations).
Usage:
%let dir=%sysfunc(pathname(work))/core;
%let repo=https://github.com/sasjs/core;
%put source clone rc=%sysfunc(GITFN_CLONE(&repo,&dir));
%mf_writefile(&dir/somefile.txt,l1=some content)
%mf_deletefile(&dir/package.json)
%mp_gitstatus(&dir,outds=work.gitstatus)
%mp_gitadd(&dir,inds=work.gitstatus)
@param [in] gitdir The directory containing the GIT repository
@param [in] inds= (work.mp_gitadd) The input dataset with the list of files
to stage. Will accept the output from mp_gitstatus(), else just use a table
with the following columns:
@li path $1024 - relative path to the file in the repo
@li staged $32 - whether the file is staged (TRUE or FALSE)
@li status $64 - either new, deleted, or modified
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
<h4> Related Files </h4>
@li mp_gitadd.test.sas
@li mp_gitstatus.sas
**/

%macro mp_gitadd(gitdir,inds=work.mp_gitadd,mdebug=0);

data _null_;
set &inds;
if STAGED ne "TRUE";
rc=git_index_add("&gitdir",cats(path),status);
if rc ne 0 or &mdebug=1 then put rc=;
run;

%mend mp_gitadd;
67 changes: 67 additions & 0 deletions base/mp_gitstatus.sas
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
@file
@brief Creates a dataset with the output from `GIT_STATUS()`
@details Uses `git_status()` to fetch the number of changed files, then
iterates through with `git_status_get()` and `git_index_add()` for each
change - which is created in an output dataset.
Usage:
%let dir=%sysfunc(pathname(work))/core;
%let repo=https://github.com/sasjs/core;
%put source clone rc=%sysfunc(GITFN_CLONE(&repo,&dir));
%mf_writefile(&dir/somefile.txt,l1=some content)
%mf_deletefile(&dir/package.json)
%mp_gitstatus(&dir,outds=work.gitstatus)
More info on these functions is in this [helpful paper](
https://www.sas.com/content/dam/SAS/support/en/sas-global-forum-proceedings/2019/3057-2019.pdf
) by Danny Zimmerman.
@param [in] gitdir The directory containing the GIT repository
@param [out] outds= (work.git_status) The output dataset to create. Vars:
@li gitdir $1024 - directory of repo
@li path $1024 - relative path to the file in the repo
@li staged $32 - whether the file is staged (TRUE or FALSE)
@li status $64 - either new, deleted, or modified
@li cnt - number of files
@li n - the "nth" file in the list from git_status()
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
<h4> Related Files </h4>
@li mp_gitstatus.test.sas
@li mp_gitadd.sas
**/

%macro mp_gitstatus(gitdir,outds=work.mp_gitstatus,mdebug=0);

data &outds;
LENGTH gitdir path $ 1024 STATUS $ 64 STAGED $ 32;
call missing (of _all_);
gitdir=symget('gitdir');
cnt=git_status(trim(gitdir));
if cnt=-1 then do;
put "The libgit2 library is unavailable and no Git operations can be used.";
put "See: https://stackoverflow.com/questions/74082874";
end;
else if cnt=-2 then do;
put "The libgit2 library is available, but the status function failed.";
put "See the log for details.";
end;
else do n=1 to cnt;
rc=GIT_STATUS_GET(n,gitdir,'PATH',path);
rc=GIT_STATUS_GET(n,gitdir,'STAGED',staged);
rc=GIT_STATUS_GET(n,gitdir,'STATUS',status);
output;
%if &mdebug=1 %then %do;
putlog (_all_)(=);
%end;
end;
rc=git_status_free(gitdir);
drop rc cnt;
run;

%mend mp_gitstatus;
14 changes: 14 additions & 0 deletions sasjs/sasjsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@
"allowInsecureRequests": false
},
"appLoc": "/sasjs/core",
"deployConfig": {
"deployServicePack": true,
"deployScripts": []
},
"macroFolders": [
"server",
"tests/serveronly"
Expand Down Expand Up @@ -105,6 +109,16 @@
"deployServicePack": true
},
"contextName": "SAS Job Execution compute context"
},
{
"name": "sasjs9",
"serverUrl": "https://sas9.4gl.io",
"serverType": "SASJS",
"appLoc": "/Public/app/sasjs9",
"deployConfig": {
"deployServicePack": true,
"deployScripts": []
}
}
]
}
224 changes: 224 additions & 0 deletions sasjs/utils/create_sas_package.sas
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
/**
@file
@brief Deploy repo as a SAS PACKAGES module
@details After every release, this program is executed to update the SASPAC
repo with the latest macros (and same version number).
The program is first compiled using sasjs compile, then executed using
sasjs run.
Requires the server to have SSH keys.
<h4> SAS Macros </h4>
@li mp_gitadd.sas
@li mp_gitreleaseinfo.sas
@li mp_gitstatus.sas
**/


/* get package version */
%mp_gitreleaseinfo(GITHUB,sasjs/core,outlib=splib)
data _null_;
set splib.root;
call symputx('version',TAG_NAME);
run;

/* clone the source repo */
%let dir = %sysfunc(pathname(work))/core;
%put source clone rc=%sysfunc(GITFN_CLONE(https://github.com/sasjs/core,&dir));


/*
clone the target repo.
If you have issues, see: https://stackoverflow.com/questions/74082874
*/
options dlcreatedir;
libname _ "&dirOut.";
%let dirOut = %sysfunc(pathname(work))/package;
%put tgt clone rc=%sysfunc(GITFN_CLONE(
[email protected]:allanbowe/sasjscore.git,
&dirOut,
git,
%str( ),
/home/sasjssrv/.ssh/id_ecdsa.pub,
/home/sasjssrv/.ssh/id_ecdsa
));


/*
Prepare Package Metadata
*/
data _null_;
infile CARDS4;
file "&dirOut./description.sas";
input;
if _infile_ =: 'Version:' then put "Version: &version.";
else put _infile_;
CARDS4;
Type: Package
Package: SASjsCore
Title: SAS Macros for Application Development
Version: $(PLACEHOLDER)
Author: Allan Bowe
Maintainer: 4GL Ltd
License: MIT
Encoding: UTF8

DESCRIPTION START:

The SASjs Macro Core library is a component of the SASjs framework, the
source for which is avaible here: https://github.com/sasjs

Macros are divided by:

* Macro Functions (prefix mf_)
* Macro Procedures (prefix mp_)
* Macros for Metadata (prefix mm_)
* Macros for SASjs Server (prefix ms_)
* Macros for Viya (prefix mv_)
DESCRIPTION END:
;;;;
run;

/*
Prepare Package License
*/
data _null_;
file "&dirOut./license.sas";
infile "&dir/LICENSE";
input;
put _infile_;
run;

/*
Extract Core files into MacroCore Package location
*/
data members(compress=char);
length dref dref2 $ 8 name name2 $ 32 path $ 2048;
rc = filename(dref, "&dir.");
put dref=;
did = dopen(dref);
if did then
do i = 1 to dnum(did);
name = dread(did, i);
if name in
("base" "ddl" "fcmp" "lua" "meta" "metax" "server" "viya" "xplatform")
then do;
rc = filename(dref2,catx("/", "&dir.", name));
put dref2= name;
did2 = dopen(dref2);

if did2 then
do j = 1 to dnum(did2);
name2 = dread(did2, j);
path = catx("/", "&dir.", name, name2);
if "sas" = scan(name2, -1, ".") then output;
end;
rc = dclose(did2);
rc = filename(dref2);
end;
end;
rc = dclose(did);
rc = filename(dref);
keep name name2 path;
run;

%let temp_options = %sysfunc(getoption(source)) %sysfunc(getoption(notes));
options nosource nonotes;
data _null_;
set members;
by name notsorted;

ord + first.name;

if first.name then
do;
call execute('libname _ '
!! quote(catx("/", "&dirOut.", put(ord, z3.)!!"_macros"))
!! ";"
);
put @1 "./" ord z3. "_macros/";
end;

put @10 name2;
call execute("
data _null_;
infile " !! quote(strip(path)) !! ";
file " !! quote(catx("/", "&dirOut.", put(ord, z3.)!!"_macros", name2)) !!";
input;
select;
when (2 = trigger) put _infile_;
when (_infile_ = '/**') do; put '/*** HELP START ***//**'; trigger+1; end;
when (_infile_ = '**/') do; put '**//*** HELP END ***/'; trigger+1; end;
otherwise put _infile_;
end;
run;");

run;
options &temp_options.;

/*
Generate SASjsCore Package
*/
%GeneratePackage(
filesLocation=&dirOut
)

/**
* apply new version in a github action
* 1. create folder
* 2. create template yaml
* 3. replace version number
*/

%mf_mkdir(&dirout/.github/workflows)

%let desc=Version &version of sasjs/core is now on SAS PACKAGES :ok_hand:;
data _null_;
file "&dirout/.github/workflows/release.yml";
put "name: SASjs Core Package Publish Tag";
put "on:";
put " push:";
put " branches:";
put " - main";
put "jobs:";
put " update:";
put " runs-on: ubuntu-latest";
put " steps:";
put " - uses: actions/checkout@master";
put " - name: Make Release";
put " uses: alice-biometrics/release-creator/@v1.0.5";
put " with:";
put " github_token: ${{ secrets.GH_TOKEN }}";
put " branch: main";
put " draft: false";
put " version: &version";
put " description: '&desc'";
run;


/**
* Add, Commit & Push!
*/
%mp_gitstatus(&dirout,outds=work.gitstatus,mdebug=1)
%mp_gitadd(&dirout,inds=work.gitstatus,mdebug=1)

data _null_;
rc=gitfn_commit("&dirout"
,"HEAD","&sysuserid","sasjs@core"
,"FEAT: Releasing &version"
);
put rc=;
rc=git_push(
"&dirout"
,"git"
,""
,"/home/sasjssrv/.ssh/id_ecdsa.pub"
,"/home/sasjssrv/.ssh/id_ecdsa"
);
run;




Loading

0 comments on commit f832e93

Please sign in to comment.