Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/m365/spfx/commands/project/DeployWorkflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export const workflow: GitHubWorkflow = {
jobs: {
"build-and-deploy": {
"runs-on": "ubuntu-latest",
env: {
NodeVersion: "22.x"
Comment thread
Adam-it marked this conversation as resolved.
},
steps: [
{
name: "Checkout",
Expand All @@ -22,7 +25,7 @@ export const workflow: GitHubWorkflow = {
name: "Use Node.js",
uses: "actions/setup-node@v4",
with: {
"node-version": "18.x"
"node-version": "${{ env.NodeVersion }}"
}
},
{
Expand Down Expand Up @@ -109,6 +112,10 @@ export const pipeline: AzureDevOpsPipeline = {
{
name: "SiteAppCatalogUrl",
value: ""
},
{
name: "NodeVersion",
value: "22.x"
}
],
stages: [
Expand All @@ -122,7 +129,7 @@ export const pipeline: AzureDevOpsPipeline = {
task: "NodeTool@0",
displayName: "Use Node.js",
inputs: {
versionSpec: "18.x"
versionSpec: "$(NodeVersion)"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ describe(commands.PROJECT_AZUREDEVOPS_PIPELINE_ADD, () => {
afterEach(() => {
sinonUtil.restore([
(command as any).getProjectRoot,
(command as any).getProjectVersion,
fs.existsSync,
fs.readFileSync,
fs.writeFileSync
Expand Down Expand Up @@ -90,8 +89,6 @@ describe(commands.PROJECT_AZUREDEVOPS_PIPELINE_ADD, () => {
return '';
});

sinon.stub(command as any, 'getProjectVersion').returns('1.16.0');

const writeFileSyncStub: sinon.SinonStub = sinon.stub(fs, 'writeFileSync').resolves({});

await command.action(logger, { options: { name: 'test', branchName: 'dev', skipFeatureDeployment: true, loginMethod: 'user', scope: 'sitecollection', siteUrl: 'https://contoso.sharepoint.com/sites/project' } } as any);
Expand Down Expand Up @@ -132,7 +129,6 @@ describe(commands.PROJECT_AZUREDEVOPS_PIPELINE_ADD, () => {

it('creates a default workflow (debug)', async () => {
sinon.stub(command as any, 'getProjectRoot').returns(path.join(process.cwd(), projectPath));

sinon.stub(fs, 'existsSync').callsFake((fakePath) => {
if (fakePath.toString().endsWith('.azuredevops')) {
return true;
Expand All @@ -152,38 +148,6 @@ describe(commands.PROJECT_AZUREDEVOPS_PIPELINE_ADD, () => {
return '';
});

sinon.stub(command as any, 'getProjectVersion').returns('1.16.0');

const writeFileSyncStub: sinon.SinonStub = sinon.stub(fs, 'writeFileSync').resolves({});

await command.action(logger, { options: { debug: true } } as any);
assert(writeFileSyncStub.calledWith(path.join(process.cwd(), projectPath, '/.azuredevops', 'pipelines', 'deploy-spfx-solution.yml')), 'workflow file not created');
});

it('creates a default workflow for SPFx 1.18.x', async () => {
sinon.stub(command as any, 'getProjectRoot').returns(path.join(process.cwd(), projectPath));

sinon.stub(fs, 'existsSync').callsFake((fakePath) => {
if (fakePath.toString().endsWith('.azuredevops')) {
return true;
}
else if (fakePath.toString().endsWith('pipelines')) {
return true;
}

return false;
});

sinon.stub(fs, 'readFileSync').callsFake((path, options) => {
if (path.toString().endsWith('package.json') && options === 'utf-8') {
return '{"name": "test"}';
}

return '';
});

sinon.stub(command as any, 'getProjectVersion').returns('1.18.0');

const writeFileSyncStub: sinon.SinonStub = sinon.stub(fs, 'writeFileSync').resolves({});

await command.action(logger, { options: { debug: true } } as any);
Expand Down Expand Up @@ -212,101 +176,9 @@ describe(commands.PROJECT_AZUREDEVOPS_PIPELINE_ADD, () => {
return false;
});

sinon.stub(command as any, 'getProjectVersion').returns('1.18.0');

sinon.stub(fs, 'writeFileSync').callsFake(() => { throw 'error'; });

await assert.rejects(command.action(logger, { options: {} } as any),
new CommandError('error'));
});

it('handles error with unknown version of SPFx', async () => {
sinon.stub(command as any, 'getProjectRoot').returns(path.join(process.cwd(), projectPath));

sinon.stub(fs, 'readFileSync').callsFake((path, options) => {
if (path.toString().endsWith('package.json') && options === 'utf-8') {
return '{"name": "test"}';
}

return '';
});

sinon.stub(fs, 'existsSync').callsFake((fakePath) => {
if (fakePath.toString().endsWith('.azuredevops')) {
return true;
}
else if (fakePath.toString().endsWith('pipelines')) {
return true;
}

return false;
});

sinon.stub(command as any, 'getProjectVersion').returns(undefined);

sinon.stub(fs, 'writeFileSync').callsFake(() => { throw 'error'; });

await assert.rejects(command.action(logger, { options: {} } as any),
new CommandError(`Unable to determine the version of the current SharePoint Framework project`, undefined));
});

it('handles error with unknown minor version of SPFx when missing minor version', async () => {
sinon.stub(command as any, 'getProjectRoot').returns(path.join(process.cwd(), projectPath));

sinon.stub(fs, 'readFileSync').callsFake((path, options) => {
if (path.toString().endsWith('package.json') && options === 'utf-8') {
return '{"name": "test"}';
}

return '';
});

sinon.stub(fs, 'existsSync').callsFake((fakePath) => {
if (fakePath.toString().endsWith('.azuredevops')) {
return true;
}
else if (fakePath.toString().endsWith('pipelines')) {
return true;
}

return false;
});

sinon.stub(command as any, 'getProjectVersion').returns('1');

sinon.stub(fs, 'writeFileSync').callsFake(() => { throw 'error'; });

await assert.rejects(command.action(logger, { options: {} } as any),
new CommandError(`Unable to determine the minor version of the current SharePoint Framework project`, undefined));
});

it('handles error with unknown minor version of SPFx when minor version is NaN', async () => {
sinon.stub(command as any, 'getProjectRoot').returns(path.join(process.cwd(), projectPath));

sinon.stub(fs, 'readFileSync').callsFake((path, options) => {
if (path.toString().endsWith('package.json') && options === 'utf-8') {
return '{"name": "test"}';
}

return '';
});

sinon.stub(fs, 'existsSync').callsFake((fakePath) => {
if (fakePath.toString().endsWith('.azuredevops')) {
return true;
}
else if (fakePath.toString().endsWith('pipelines')) {
return true;
}

return false;
});

sinon.stub(command as any, 'getProjectVersion').returns('1.aaa.0');

sinon.stub(fs, 'writeFileSync').callsFake(() => { throw 'error'; });

await assert.rejects(command.action(logger, { options: {} } as any),
new CommandError(`Unable to determine the minor version of the current SharePoint Framework project`, undefined));
});
});
26 changes: 0 additions & 26 deletions src/m365/spfx/commands/project/project-azuredevops-pipeline-add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import { pipeline } from './DeployWorkflow.js';
import { fsUtil } from '../../../../utils/fsUtil.js';
import { AzureDevOpsPipeline, AzureDevOpsPipelineStep } from './project-azuredevops-pipeline-model.js';
import GlobalOptions from '../../../../GlobalOptions.js';
import { parse } from 'semver';


interface CommandArgs {
options: Options;
Expand Down Expand Up @@ -157,25 +155,6 @@ class SpfxProjectAzureDevOpsPipelineAddCommand extends BaseProjectCommand {
pipeline.trigger.branches.include[0] = options.branchName;
}

const version = this.getProjectVersion();

if (!version) {
throw `Unable to determine the version of the current SharePoint Framework project`;
}

const minorVersion = parse(version)?.minor;

if (minorVersion === undefined) {
throw `Unable to determine the minor version of the current SharePoint Framework project`;
}

if (minorVersion < 18) {
const node = this.getNodeAction(pipeline);
if (node.inputs) {
node.inputs.versionSpec = '16.x';
}
}

const script = this.getScriptAction(pipeline);
if (script.script) {
if (options.loginMethod === 'user') {
Expand Down Expand Up @@ -229,11 +208,6 @@ class SpfxProjectAzureDevOpsPipelineAddCommand extends BaseProjectCommand {
return steps.find(step => step.script)!;
}

private getNodeAction(pipeline: AzureDevOpsPipeline): AzureDevOpsPipelineStep {
const steps = this.getPipelineSteps(pipeline);
return steps.find(step => step.task && step.task.indexOf('NodeTool') >= 0)!;
}

private getPipelineSteps(pipeline: AzureDevOpsPipeline): AzureDevOpsPipelineStep[] {
return pipeline.stages[0].jobs[0].steps;
}
Expand Down
Loading