Merge pull request 'fix(7.22): clear the makedata poll on destroy, and close the release-gate findings' (#477) from fix/7.22-release-followups into release/7.22
Sites / deploy (push) Successful in 3m6s
Build / Build-and-ng-test (pull_request) Successful in 6m18s
Lighthouse Checks / lighthouse (pull_request) Successful in 8m47s
Build / Build-and-test-development (pull_request) Successful in 27m24s

Reviewed-on: #477
This commit was merged in pull request #477.
This commit is contained in:
allan committed 2026-11-05 17:58:28 +00:00
commit eef91ce989
7 files changed
+73 -25

No files matched your search

+4 -2
View File
@@ -190,13 +190,15 @@ jobs:
key: angular-v1-${{ github.base_ref }}-${{ hashFiles('client/package-lock.json') }}
- name: Check audit
# Audit should fail and stop the CI on any vulnerability in root and sas, and on low+ in client
# Root and sas fail on moderate and above (npm's default), client on
# low and above - the flags below are what makes that true, so they have
# to stay in step with this comment.
run: |
npm audit --omit=dev
cd ./sas
npm audit --omit=dev
cd ../client
npm audit --omit=dev
npm audit --omit=dev --audit-level=low
- name: Check archiver directory walk
# the readdir-glob minimatch override in client/package.json is a major
+6 -4
View File
@@ -50,19 +50,21 @@ jobs:
fi
# .gitea/scripts/ carries the runner-memory gate this job runs before
# it starts, so a change there has to be exercised too.
if printf '%s\n' "$CHANGED" | grep -qE '^(client/|sas/mocks/|\.gitea/scripts/|package-lock\.json|\.gitea/workflows/lighthouse\.yaml)'; then
# it starts, so a change there has to be exercised too. sas/package.json
# is what this job reads for the @sasjs/cli pin below, so a bump there
# has to be audited as well - build.yaml's matcher covers it too.
if printf '%s\n' "$CHANGED" | grep -qE '^(client/|sas/mocks/|sas/package\.json|\.gitea/scripts/|package-lock\.json|\.gitea/workflows/lighthouse\.yaml)'; then
echo "client=true" >> "$GITHUB_OUTPUT"
else
echo "client=false" >> "$GITHUB_OUTPUT"
echo "::notice::Lighthouse audit skipped - nothing under client/, sas/mocks/ or .gitea/scripts/ changed"
echo "::notice::Lighthouse audit skipped - nothing under client/, sas/mocks/, sas/package.json or .gitea/scripts/ changed"
printf 'Skipping the audit - nothing it reads changed:\n%s\n' "$CHANGED"
fi
- name: Lighthouse audit not run - no client changes
if: steps.changes.outputs.client == 'false'
run: |
echo "No client, sas/mocks or .gitea/scripts change in this pull request - the audit was skipped by design."
echo "No client, sas/mocks, sas/package.json or .gitea/scripts change in this pull request - the audit was skipped by design."
echo "The detection step above lists the files it saw, and warns instead if it could not decide (in which case the audit runs)."
- name: Check runner size
+4 -1
View File
@@ -99,7 +99,10 @@ jobs:
# client install scripts are off (client/.npmrc); the generator that
# creates src/environments/version.ts runs explicitly
npm run postinstall
npm i webpack
# webpack comes from the client lockfile, so install the version it
# already resolves rather than whatever is current at release time
WEBPACK_VERSION=$(node -p "require('./package-lock.json').packages['node_modules/webpack'].version")
npm i --no-save "webpack@${WEBPACK_VERSION}"
npm run build
shell: bash
env:
@@ -156,6 +156,10 @@ describe('AutomaticComponent (Viya setup)', () => {
opened.push(String(url))
return null
})
// The real poll loads the page once it sees makedata finish: left running
// here it fires five seconds later, during whichever spec is running then,
// and Karma aborts with "Some of your tests did a full page reload".
spyOn(component as any, 'pollMakedataCompletion')
component.runMakedataInNewWindow({
contextName: 'SAS Job Execution & co',
@@ -170,6 +174,25 @@ describe('AutomaticComponent (Viya setup)', () => {
expect(opened[0]).toContain('&admin=group%201%2B2')
})
it('stops the makedata poll when the screen is destroyed', () => {
// The poll runs every five seconds for up to ten minutes and reloads the
// page the first time it sees makedata gone. It must not outlive the
// screen: a timer left behind reloads whatever the user moved on to.
const { component } = build()
spyOn(window, 'open')
component.runMakedataInNewWindow({
contextName: 'Compute Reusable',
admin: 'viyagroup18',
dcPath: '/export/dc'
})
expect((component as any).makedataPollInterval).not.toBeNull()
component.ngOnDestroy()
expect((component as any).makedataPollInterval).toBeNull()
})
it('starts the job when deploy is pressed', () => {
// The screen's only button calls this; a version where it stopped doing so
// would leave the setup page unable to do anything at all.
@@ -2,6 +2,7 @@ import {
Component,
EventEmitter,
Input,
OnDestroy,
OnInit,
Output,
ViewEncapsulation
@@ -39,7 +40,7 @@ export interface ComputeContextInfo {
encapsulation: ViewEncapsulation.None,
standalone: false
})
export class AutomaticComponent implements OnInit {
export class AutomaticComponent implements OnInit, OnDestroy {
@Input() sasJs!: SASjs
@Input() sasJsConfig: SASjsConfig = new SASjsConfig()
@Input() dcAdapterSettings: DcAdapterSettings | undefined
@@ -564,10 +565,25 @@ export class AutomaticComponent implements OnInit {
private makedataPollInterval: any = null
private pollMakedataCompletion() {
/**
* The poll outlives the deploy screen if the user navigates away, and it
* loads the page again the moment it sees makedata finish. Stop it with the
* component, so a timer cannot reload the page from under whatever the user
* moved on to.
*/
ngOnDestroy(): void {
this.stopMakedataPoll()
}
private stopMakedataPoll(): void {
if (this.makedataPollInterval) {
clearInterval(this.makedataPollInterval)
this.makedataPollInterval = null
}
}
private pollMakedataCompletion() {
this.stopMakedataPoll()
let attempts = 0
const maxAttempts = 120 // 10 minutes at 5s intervals
@@ -584,8 +600,7 @@ export class AutomaticComponent implements OnInit {
console.log(
'pollMakedataCompletion: makedata job is gone, reloading app'
)
clearInterval(this.makedataPollInterval)
this.makedataPollInterval = null
this.stopMakedataPoll()
// Reload the app fresh from the SASJobExecution URL
window.location.href = window.location.href.split('#')[0]
@@ -598,8 +613,7 @@ export class AutomaticComponent implements OnInit {
console.warn(
'pollMakedataCompletion: timed out after 10 minutes, stopping poll'
)
clearInterval(this.makedataPollInterval)
this.makedataPollInterval = null
this.stopMakedataPoll()
}
}, 5000)
}
+8 -6
View File
@@ -32,11 +32,11 @@
/*
These macros write their JSON answer to _webout. Point it at a temporary
file while they run and put it back afterwards, so the test's own result -
which the term program writes to _webout - still reaches the caller. The
assertions read the work datasets the macros build, not the JSON.
file while they run; the term program's %webout(OPEN) assigns _webout again
before it dumps the results, so the test's own result still reaches the
caller. The assertions read the work datasets the macros build, not the
JSON.
*/
%let _webout_path=%sysfunc(pathname(_webout));
filename _webout temp;
%let root=%sysfunc(pathname(work))/dirlist%mf_getuniquefileref();
@@ -169,9 +169,11 @@ run;
)
/*
hand _webout back before the results are dumped
Nothing to hand back: on JES _webout is a filesrvc fileref whose pathname()
is empty, so restoring it by path fails with "Invalid physical name" and
leaves the temporary file in place. The term program's %webout(OPEN)
assigns _webout itself before it dumps the results.
*/
filename _webout "&_webout_path" mod;
/**
* dump results to the log for offline inspection
+8 -6
View File
@@ -25,11 +25,11 @@
/*
These macros write their JSON answer to _webout. Point it at a temporary
file while they run and put it back afterwards, so the test's own result -
which the term program writes to _webout - still reaches the caller. The
assertions read the work datasets the macros build, not the JSON.
file while they run; the term program's %webout(OPEN) assigns _webout again
before it dumps the results, so the test's own result still reaches the
caller. The assertions read the work datasets the macros build, not the
JSON.
*/
%let _webout_path=%sysfunc(pathname(_webout));
filename _webout temp;
%let root=%sysfunc(pathname(work))/checkwrite%mf_getuniquefileref();
@@ -125,9 +125,11 @@ run;
)
/*
hand _webout back before the results are dumped
Nothing to hand back: on JES _webout is a filesrvc fileref whose pathname()
is empty, so restoring it by path fails with "Invalid physical name" and
leaves the temporary file in place. The term program's %webout(OPEN)
assigns _webout itself before it dumps the results.
*/
filename _webout "&_webout_path" mod;
/**
* dump results to the log for offline inspection