makeDataServer.json seeded ADMIN=AllUsers, a Viya-style group that no account on the shared estate belongs to. The seed still reports SUCCESS with a group the caller is not in, and then every getdata/stagedata call aborts with '<user> is not authorised to edit <libds> in the MPE_SECURITY table', which reads like a broken deployment. The estate's accounts are in all-users, the SASjs Server group every logged-in user has, so seed with that and describe the rule in the estate-testing skill rather than telling the reader to override the shipped value.
8.3 KiB
name, description
| name | description |
|---|---|
| dc-estate-testing | Use when deploying Data Controller to a shared SASjs Server estate (sas.4gl.io) or running the SAS test suite against it. Covers the target and credential setup, the makedata seed the suite needs on a fresh appLoc and the group it must name, how to read the results, and how to deploy the frontend so the streamed app is the build you just made. |
Deploying and testing on the shared SASjs Server estate
The whole cycle is two npm scripts plus sasjs test. Everything below explains what those scripts do and the steps that go wrong.
cd sas && npm ci # macro dependencies
cd ../client && npm ci && npm run build # frontend only - see "Deploying the frontend"
cd ../sas && npm run server # cpfavicon + sasjs cbd -t server + makedata
npx sasjs test -t server
npm run server is sasjs cbd -t server && npm run serverdata, and the seed in the second half is not optional. sasjs cbd on its own deploys the services and the test programs but leaves the appLoc with no Data Controller configuration, and testsetup reads <appLoc>/services/public/settings.sas through the drive API. makedata is what creates that file, so without the seed testsetup gets a 404, aborts, and 59 of the 64 test programs fail to complete on setup alone - which reads like a broken deployment rather than a missing seed.
The targets
server is the shared estate: serverType: SASJS on https://sas.4gl.io, appLoc /Public/app/dc, a real SAS 9 binary behind SASjs Server (GET /SASjsApi/info reports mode: server, runTimes: ["sas"], localLoginEnabled: true). 4gl is the same estate with a slightly different config, hence the older npm run 4gl / 4glmakedata pair.
A run against server exercises the SASjs Server branch of every macro and the SAS 9 backend, and nothing else: no Viya branch, no SAS 9 STP branch. Say that when reporting, rather than implying the matrix is covered.
To deploy your own branch without replacing the app everyone else uses, add a target that copies server and changes appLoc and streamServiceName (for example /Public/app/<you>/dc), keep it out of the commit, and pass it with -t. sasjs cbd overwrites the whole appLoc it is pointed at.
Credentials
The CLI logs in with a registered client, not a username and password: .env.<target> (gitignored, mode 600) needs CLIENT, ACCESS_TOKEN and REFRESH_TOKEN. With CLIENT alone it prints a /SASjsLogon?client_id=... URL and waits for an authorization code, which cannot be answered headless.
Mint the pair from a local login, with the password read from a file rather than argv:
GET /with a cookie jar - it setsXSRF-TOKEN, which every POST must echo in anX-XSRF-TOKENheader.POST /SASLogon/loginwith{"username","password"}.GET /SASjsApi/clienton the same session - the registered client ids.POST /SASLogon/authorizewith{"clientId"}->{"code"}.POST /SASjsApi/auth/tokenwith{"clientId","code"}->accessToken/refreshToken.
An unmatched /SASjsApi/... path answers 200 with the Swagger page, so check the content type; HTML means the route does not exist. Delete the token file when the run is over.
The makedata seed
npm run serverdata sends deploy/makeDataServer.json: one fromjs row with ADMIN, DCPATH and OUTFMT. Two things about it are worth knowing before you trust its result.
ADMINmust name a group the calling account is actually in. The shipped value isall-users, the SASjs Server group that every logged-in user is a member of, which is what the shared estate needs. A name the account is not in - a Viya-style group such asAllUsers, or one estate's own group carried into another - still answersSUCCESSfrom the seed, and then every latergetdata/stagedatacall aborts with<user> is not authorised to edit <lib>.<ds> in the <lib>.MPE_SECURITY table. Check what the account belongs to with a call toservices/public/getgroupsbefore changing the value.- Each run creates a new library. The response carries
STATUS,DCPATHandLIBREF(for exampleDC621835), and the LIBREF is clock-derived, so a libref from an earlier run answersdataset <lib>.<table> does not exist- take the current one from the response. KEEPMEcontrols whether the seed can be repeated. Without itmakedatadeletes itself and the configurator after a successful run (deliberately, so it cannot be executed twice over real data), and a second seed fails withThe Program at (<appLoc>/services/admin/makedata) does not existuntil you runsasjs cbdagain. A harness that reseeds between runs setsKEEPMEin the input row.- Seed once per deploy, not before every test run. The suite builds its own
dctestlibrary from the seeded control tables; reseeding in between is wasted work, and there is no need to runmakedataandsasjs testin the opposite order.
Reading the results
Results land in sas/sasjsresults/: testResults.json (the counts worth quoting: tests_with_results, tests_that_pass, failed_to_complete, completed_with_failures), testResults.csv (one row per assertion, lower-case headers test_target, test_loc, sasjs_test_id, test_suite_result, test_description, test_url), and one SAS log per program under logs/. The CLI's closing lines are not the source of truth when they disagree with the JSON.
A current green run is 64 of 64 test programs with 241 assertions passing and nothing failing to complete.
ERROR lines in the per-program logs are expected and are not a failed run: the specs that assert a refusal get ERROR: Execution canceled by an %ABORT CANCEL statement, and the ones that feed bad payloads get the rejection message they are asserting on (Invalid libds:..., Invalid libref:...). Judge the run by the JSON counts, then by whether the errors you find are the ones the tests asked for.
Deploying the frontend
The streamed web app is a separate artefact and sasjs cbd only streams it if client/dist exists:
client/libraries/sheet-crypto.tgz.gpgis an encrypted dependency (file:libraries/sheet-crypto.tgzinclient/package.json) that is not on the public registry. Decrypt it with the passphrase the maintainer holds:printf '%s' "$SHEET_PWD" | gpg --batch --yes --passphrase-fd 0 --output ./libraries/sheet-crypto.tgz --decrypt ./libraries/sheet-crypto.tgz.gpg.client/.npmrcis gitignored and needslegacy-peer-deps=true(the committed lock is written with it) plus the@sheetregistry lines.cd client && npm ci && npm run build.- The build carries the repo default appLoc, so point it at the deployment before deploying: rewrite
apploc="/Public/app/dc"indist/index.htmlto the target appLoc. cd ../sas && npx sasjs cbd -t <target>- withclient/distpresent the log saysCopying web app filesandWeb app is available at <url>.
Without step 1 the deploy prints ERROR An error has occurred when compiling web app services ... webSourcePath: .../client/dist doesn't exist and then deploys the services anyway, so the deploy looks successful while the app streams nothing. The AppStream URL is session-protected: an anonymous curl gets a 401, so verify it with a logged-in cookie jar and fetch the main.<hash>.js the page names.
Never commit client/.npmrc or the decrypted tarball; both are ignored, and git status staying clean is the check.
Reading a failed run
ERROR An error occurred while executing the request. Job location: <appLoc>/tests/...means the response was not JSON, so the program broke before it could write results. Opensasjsresults/logs/<suite>.logand read the firstERROR; a single compile break cascades into hundreds ofERROR 180-322: Statement is not validlines and the tail is noise.WARNING: Apparent symbolic reference TESTLOC not resolvedintestsetup.log, next to a404 Not Foundforservices/public/settings.sas, is the missing seed described above, not a macro problem.sasjs testruns the DEPLOYED program, so after editing a service, hook or test, runsasjs cbdagain before testing or you will debug code that is no longer in the tree.- A deployment can succeed and still be missing its web app, its data or its configuration - check the thing you changed rather than the exit code.