cli-microsoft365 icon indicating copy to clipboard operation
cli-microsoft365 copied to clipboard

New command: spfx project azuredevops pipeline add

Open Adam-it opened this issue 2 years ago β€’ 42 comments

Usage

m365 spfx project azuredevops pipeline add [options]

Description

Adds a Azure DevOps pipeline for a SharePoint Framework project.

Options

Option Description
-n, --name [name] Name of the pipeline run that will be created. If none is specified a default name generated by Azure DevOps will be used
-b, --branchName [branchName] Specify the branch name which should trigger the workflow on push. If none is specified a default will be used which is 'main'
-l, --loginMethod [loginMethod] Specify the login method used for the login action. Possible options are: user, application. Default application
-s, --scope [scope] Scope of the app catalog: tenant, sitecollection. Default is tenant
--siteUrl [siteUrl] The URL of the site collection where the solution package will be added. Required if scope is set to sitecollection
--skipFeatureDeployment When specified the app will be added to all sites. When deployed to the site app catalog it will be added to all sub-sites of that site.

Examples

Adds an Azure DevOps Pipeline for a SharePoint Framework project triggered on push to main

m365 spfx project azuredevops pipeline add

Adds an Azure DevOps Pipeline for a SharePoint Framework project with user login method triggered on push to main

m365 spfx project azuredevops pipeline add --loginMethod "user"

Adds an Azure DevOps Pipeline for a SharePoint Framework project with deployment to a site collection app catalog that will overwrite any existing packages with same name

m365 spfx project azuredevops pipeline add --scope "sitecollection" --siteUrl "https://some.sharepoint.com/sites/someSite" --overwrite

Default properties

No response

Additional Info

The implementation should be very similar to spfx project github workflow add so we should store the pipeline definition as JSON and use yaml npm package that we already have to parse the .json definition to the .yml file. The pipeline should be created in .azuredevops\pipelines directory (the command should create one if doesn't exist) and the file name should be deploy-spfx-solution.yml so it is consistent with Azure DevOps convention and also with the current GitHub command output. Below we may see a project with both pipeline for azdo and workflow for gh image

The command should generate the following file (or similar one depending on the options specified) I added comments in the yaml so that it is clear how the yaml should differ based on the options set. We should generate the yaml without those comments of course πŸ˜‰

name: test  # this line is optional and should only be present if the used specified the name option. Otherwise we should remove it and don't specify any name. In that case Azure DevOps generates default naming based on date and run number.

trigger:
  branches:
    include:
      - main # depends on what user passed in option branchName. default is main

pool:
  vmImage: "ubuntu-latest"

variables:
  - name: CertificateBase64Encoded # this should be visible only when application login method was used which is the default one.
    value: "" # this should be filled manually by the user
  - name: CertificateSecureFileId # this should be visible only when application login method was used which is the default one
    value: "" # this should be filled manually by the user
  - name: CertificatePassword # this should be visible only when application login method was used which is the default one
    value: "" # this should be filled manually by the user
  - name: EntraIDAppId # this should be visible only when application login method was used which is the default one
    value: "" # this should be filled manually by the user
  - name: UserName # this should be visible only when user login method was used
    value: "" # this should be filled manually by the user
  - name: Password # this should be visible only when user login method was used
    value: "" # this should be filled manually by the user
  - name: TenantId
    value: "2942bb31-1d49-4da6-8d3d-d0f9e1141486" # I think we should be able to retrive that and prefil. But only if the user is logged in as the spfx commands do not require being logged in to m365 tenant
  - name: SharePointBaseUrl
    value: "https://tenanttocheck.sharepoint.com"  # I think we should be able to retrive that and prefil. But only if the user is logged in as the spfx commands do not require being logged in to m365 tenant
  - name: PackageName
    value: "demo-1.sppkg" # we should prefil that
  - name: SiteAppCatalogUrl # this option and it's value should only be present in the flow if the siteUrl option was used in the command
    value: "https://tenanttocheck.sharepoint.com/sites/PnPDemo2/AppCatalog"

stages:
  - stage: "Build_and_Deploy"
    jobs:
      - job: "Build_and_Deploy"
        steps:
          - task: NodeTool@0
            displayName: "Use Node.js"
            inputs:
              versionSpec: "18.x"

          - task: Npm@1
            displayName: "Run npm install"
            inputs:
              command: "install"

          - task: Gulp@0
            displayName: "Gulp bundle"
            inputs:
              gulpFile: ./gulpfile.js
              targets: bundle
              arguments: "--ship"

          - task: Gulp@0
            displayName: "Gulp package"
            inputs:
              targets: "package-solution"
              arguments: "--ship"

          - task: Npm@1
            displayName: "Install CLI for Microsoft 365"
            inputs:
              command: custom
              verbose: false
              customCommand: "install -g @pnp/cli-microsoft365"

          - script: |
              m365 login --authType certificate --certificateBase64Encoded "$(CertificateBase64Encoded)" --password "$(CertificatePassword)" --appId "$(EntraIDAppId)" --tenant "$(TenantId)"
              m365 spo set --url "$(SharePointBaseUrl)"
              m365 spo app add --filePath "$(Build.SourcesDirectory)/sharepoint/solution/$(PackageName)" --overwrite
              m365 spo app deploy --name "$(PackageName)" --appCatalogScope sitecollection --appCatalogUrl "($SiteAppCatalogUrl)"
            displayName: "CLI for Microsoft 365 Deploy App"

           # if the site scop was set and the siteUrl option was set we should replace the m365 spo app add command so that it targets siteAppCatalog like
           # m365 spo app add --filePath "$(Build.SourcesDirectory)/sharepoint/solution/$(PackageName)" --appCatalogScope sitecollection --appCatalogUrl "($SiteAppCatalogUrl)" 

          # if skipFeatureDeployment option was set then the m365 spo app deploy command in hte aboce script should have an --skipFeatureDeployment flag as well
          
          # if user login method was used in the command then we should replace the m365 login command in the above script with this one (along with the variables which are present in the upper part of the yaml pipeline
          # m365 login --authType password --userName "$(UserName)" --password "$(Password)"

The above yaml sample is a checked use case that works image It is the simplest pipeline possible to get a CI/CD flow and get dev kicked off with development. The steps in this flow are also aligned with our m365 spfx github workflow add command

Similar to github workflow add command we should add remarks section explaining that application login method is preferable and ready for production use. the user login method will not work with an account that has MFA. We should also explain that this command only generates the yaml file. After that user need to push it to Azure DevOps and manually create the pipelien based on an existing yaml file. We may provide guidance for those manual steps. Along the way we may mention that it is preferable not to keep those variables in the yaml file but keep them as a dedicated variable group in using library feature in Azure DevOps. Additionally for application login method we should provide guidance that the user should either use CertificateBase64Encoded or CertificateSecureFileId not both

Adam-it avatar Jan 07 '24 01:01 Adam-it

@pnp/cli-for-microsoft-365-maintainers awaiting feedback πŸ™‚ @martinlingstuyl I think you are going to like this command πŸ˜‰

Adam-it avatar Jan 07 '24 01:01 Adam-it

Nice @Adam-it! I'll give it a read later!

martinlingstuyl avatar Jan 07 '24 06:01 martinlingstuyl

Awesome! I love the sane defaults. Ship it!

waldekmastykarz avatar Jan 07 '24 13:01 waldekmastykarz

Nice spec @Adam-it! I've fixed a small typo for scope. In my opinion, we should reformulate the description for skipFeatureDeployment. Currently it is:

When specified and the app supports tenant-wide deployment, deploy it to the whole tenant.

But in fact, you can also enable skip feature deployment in a site collection app catalog. The difference here is that the app is by default installed in all sub-sites instead of the entire tenant.

milanholemans avatar Jan 07 '24 14:01 milanholemans

Nice spec @Adam-it! I've fixed a small typo for scope.

Thank you

In my opinion, we should reformulate the description for skipFeatureDeployment. Currently it is:

When specified and the app supports tenant-wide deployment, deploy it to the whole tenant.

But in fact, you can also enable skip feature deployment in a site collection app catalog. The difference here is that the app is by default installed in all sub-sites instead of the entire tenant.

Good point. Let's do that. Along the way we may do the same for github workflow add command as it is the same

Adam-it avatar Jan 07 '24 14:01 Adam-it

Hi @Adam-it, looks fantastic, I'm reading through it now.

About the --overwrite option: is that really necessary? It seems to me that when you deploy an application using ci/cd, it should always overwrite the existing package...

About the certificate base64 string: wouldn't it be better if we used a secure file in the DevOps library for this? It is more secure and also easier to get a file than a base64 encoded one...

martinlingstuyl avatar Jan 07 '24 17:01 martinlingstuyl

Hi @Adam-it, looks fantastic, I'm reading through it now.

About the --overwrite option: is that really necessary? It seems to me that when you deploy an application using ci/cd, it should always overwrite the existing package...

Hmmm, makes a lot of sense. Shouldn't we align it also in GitHub workflow command? But this will be a breaking change there πŸ€”

Adam-it avatar Jan 07 '24 17:01 Adam-it

About the certificate base64 string: wouldn't it be better if we used a secure file in the DevOps library for this? It is more secure and also easier to get a file than a base64 encoded one...

Also: don't forget this part of my comment πŸ˜€ I edited it after

martinlingstuyl avatar Jan 07 '24 17:01 martinlingstuyl

Shouldn't we align it also in GitHub workflow command? But this will be a breaking change there πŸ€”

Maybe schedule this as on hold for v8?

martinlingstuyl avatar Jan 07 '24 17:01 martinlingstuyl

About the certificate base64 string: wouldn't it be better if we used a secure file in the DevOps library for this? It is more secure and also easier to get a file than a base64 encoded one...

Also: don't forget this part of my comment πŸ˜€ I edited it after

Yes and no. I did it this way because

  • it is exactly the same like we have in github workflow add command and I wanted to make those commands inputs and output really aligned.
  • secure file is 'problematic' as it may not be an input in the flow itself. Here the user would always need to create a variable group, which I agree is highly recommend, but would require additional manual steps which we would need to describe in the docs as required, which means the user also would need to read the doc and understand it 😜. For someone new to Azure DevOps an YAML pipelines that wants an easiest possible CI/CD flow the approach I speced is perfect, at least IMO. Of course if someone wants to improve the flow, like moving the vars outside of the YAML, or adding a step that runs test them sure this is recommended. But the command will give you the easiest flow possible which works and is a perfect starting point and in a way during development is good enough
  • Getting a base64 is an additional line in PS which I would also add in the docs.

Adam-it avatar Jan 07 '24 18:01 Adam-it

secure file is 'problematic' as it may not be an input in the flow itself. Here the user would always need to create a variable group

A secure file would not require a variable group persΓ©. We could simply allow users to input the id of a securefile: certificateSecureFileId.

martinlingstuyl avatar Jan 07 '24 18:01 martinlingstuyl

secure file is 'problematic' as it may not be an input in the flow itself. Here the user would always need to create a variable group

A secure file would not require a variable group persΓ©. We could simply allow users to input the id of a securefile: certificateSecureFileId.

Still the general argument applies. The problem is that the user will need to go 'outside' of the YAML pipeline for additional configuration before the flow may run.

Also what about my other two arguments like similarity to GH command? Which IMO is a huge benefit as it shows how those two areas differ or are similar and helps the learning process for folks to get to know CI/CD flows in those both major environments.

Adam-it avatar Jan 07 '24 19:01 Adam-it

Still the general argument applies. The problem is that the user will need to go 'outside' of the YAML pipeline for additional configuration before the flow may run.

Sure, he may need to, but he'll need to go to DevOps anyway, as the pipeline needs to be created, based on the definition. Also: it's not either/or, we may also give both as an option, or just add this feature later on.

Also what about my other two arguments like similarity to GH command? Which IMO is a huge benefit as it shows how those two areas differ or are similar and helps the learning process for folks to get to know CI/CD flows in those both major environments.

I don't think similarity is a very strong argument here. There will be people working with DevOps or GitHub, they'll want to benefit from the strengths of the platform they're using. That it looks exactly the same is not very important. Same goes here: we may support both options for DevOps. It will still look like 99% the same anyway.

martinlingstuyl avatar Jan 07 '24 22:01 martinlingstuyl

Sure, he may need to, but he'll need to go to DevOps anyway, as the pipeline needs to be created, based on the definition. Also: it's not either/or, we may also give both as an option, or just add this feature later on.

Well you can't win them all. The command generates the flow, you need to commit, push and set it up in DevOps that's how it works. At least until CLI is not integrated with azdo πŸ˜‹. Still, the number of manual setup seems a bit less don't you agree? The problem with either/or is the confusion it may bring especially for someone totally new. I would rather provide a single and simplest path and guidance how to improve it if needed.

I don't think similarity is a very strong argument here. There will be people working with DevOps or GitHub, they'll want to benefit from the strengths of the platform they're using. That it looks exactly the same is not very important. Same goes here: we may support both options for DevOps. It will still look like 99% the same anyway.

I disagree πŸ˜‹. The general idea behind those commands is to give you a quick and simple working solution so that you may create a CI/CD pipeline in seconds at the very start (not end) of your development. It is not to give you the most advanced and tailored solution but rather a starting point and support learning yaml pipelines πŸ‘. Similarity and comparing apples to apples helps that learning, especially if you are transferring from azdo to gh or the other way around

Adam-it avatar Jan 07 '24 23:01 Adam-it

@martinlingstuyl I removed the overwrite parameter and added this as default in the script. I also added CertificateSecureFileId var in the yaml file and info that we should specify in guidance that it should be this or CertificateBase64Encoded. Although I don't necessarily agree with this, I don't have to πŸ˜…, still I think your comment is valid and it won't harm (at least too much πŸ˜‹) adding it.

@milanholemans I updated the description for the skipFeatureDeployment, but I think it is still not the best one πŸ˜…. Wanna help me out in this πŸ™? The description I use is actually taken from spo app deploy command so maybe we should also update it there πŸ€”

Thank you both for your feed πŸ‘ You rock 🀩 @pnp/cli-for-microsoft-365-maintainers anyone else πŸ™?

Adam-it avatar Jan 07 '24 23:01 Adam-it

Maybe we could use the same description that is used in the UI (the checkbox you have to click when deploying an app)

milanholemans avatar Jan 07 '24 23:01 milanholemans

Are we already set on the acronym azdo? I'm personally not a fan of this as it doesn't feel right for Azure DevOps πŸ˜…

Jwaegebaert avatar Jan 09 '24 09:01 Jwaegebaert

Something like m365 spfx project devops pipeline add would be more clear indeed.

milanholemans avatar Jan 09 '24 09:01 milanholemans

Are we already set on the acronym azdo? I'm personally not a fan of this as it doesn't feel right for Azure DevOps πŸ˜…

Internally we use AZDO when referring to Azure DevOps but maybe it's only a thing were I work πŸ€”. What would you suggest? For the GH command we have spfx project github workflow add So maybe here we should have spfx project azuredevops pipeline add

Adam-it avatar Jan 09 '24 09:01 Adam-it

Something like m365 spfx project devops pipeline add would be more clear indeed.

isn't devops a bit to general? It does not necessarily mean Azure DevOps. I think DevOps would more relate to type of work meaning everything you do around your product after the code is done to deliver it, test it, upgrade it, integrate it, maintain it etc.

Adam-it avatar Jan 09 '24 22:01 Adam-it

Everyone I know calls it just DevOps 🀷 You can say the same about our flow section. Flow is also very abstract because it actually stands for workflow instead of Power Automate.

milanholemans avatar Jan 09 '24 22:01 milanholemans

Everyone I know calls it just DevOps 🀷 You can say the same about our flow section. Flow is also very abstract because it actually stands for workflow instead of Power Automate.

isn't it named this way because at the beginning Power Autmate indeed was named Flow πŸ€”πŸ™‚. and even now Power Automate is a product that allows you to create flows so it still a bit makes sense.

I asked Copilot and 'it' also doesn't like it πŸ˜… image

Adam-it avatar Jan 09 '24 22:01 Adam-it

isn't it named this way because at the beginning Power Autmate indeed was named Flow

Yes, but for new people that never knew Microsoft Flow, it's weird.

Azure DevOps also allows you to do DevOps stuff 😊

milanholemans avatar Jan 09 '24 22:01 milanholemans

ouch sorry @milanholemans I think I misclicked somewhere and edited your post πŸ™

Yes, but for new people that never knew Microsoft Flow, it's weird.

But don't we consider changing this name for that reason πŸ€”πŸ™‚?

Azure DevOps also allows you to do DevOps stuff 😊

As well as GitHub, Jenkins... apparently also CircleCI.. never heard of it πŸ˜…πŸ˜‰

Adam-it avatar Jan 09 '24 22:01 Adam-it

But don't we consider changing this name for that reason πŸ€”πŸ™‚?

As far as I know we don't. pa is already taken by Power Apps.

As well as GitHub, Jenkins... apparently also CircleCI.. never heard of it πŸ˜…πŸ˜‰

There are also a bunch of other tools that can create workflows. Why is it not confusing? We're a Microsoft 365 tool, and the Microsoft workflow product is called Power Automate. Same with DevOps, since we're a Microsoft 365 tool, people should think about Azure DevOps.

milanholemans avatar Jan 09 '24 22:01 milanholemans

@pnp/cli-for-microsoft-365-maintainers what do you think?

Is DevOps good enough so that most of devs will recognize it as Azure DevOps and it will be clear that m365 spfx project devops pipeline add gives you a pipeline for Azure DevOps?

I would really appreciate a third (or fourth) opinion on that πŸ˜…. TBH I reeeelly don't feel it and IMO devops wont be clear enough to indicate we are producing a pipeline for Azure DevOps.

similar for the command spfx project github workflow add it is really clear in this case (yes it's long thats true πŸ˜…) but it explains exactly what we are doing. We are procuding a github workflow for your spfx project πŸ™‚

Adam-it avatar Jan 09 '24 22:01 Adam-it

There are also a bunch of other tools that can create workflows. Why is it not confusing? We're a Microsoft 365 tool, and the Microsoft workflow product is called Power Automate.

Power Automate is part of Microsoft 365. Azure DevOps ... I think it isn't. You may use Azure DevOps separately and don't do anything around M365. As an example I may be developing my WPF app and use Azure DevOps for code storage, project management and build piplines

Same with DevOps, since we're a Microsoft 365 tool, people should think about Azure DevOps.

In my feeling no. Even if we work in M365 area we may not assume that it will be Azure DevOps and not GitHub.

I think Teams Toolkit has a general command like add ci/cd workflow and then the user selects if it is Azure, GItHub or Jenkins. There is no default value so they also don't assume it will be Azure DevOps πŸ€”.

Adam-it avatar Jan 09 '24 22:01 Adam-it

I can live with azuredevops as well. devops is just more commonly used and shorter, which doesn't necessarily mean that it's better of course. Anyway, I think these two candidates are much clearer than azdo which doesn't ring a bell at all for me.

milanholemans avatar Jan 09 '24 22:01 milanholemans

thanks @milanholemans for a quite lively discussion πŸ˜…. Let's wait for other opinions on that and try to pick whatever works best for most of us. I am also ok with azuredevops it's just devops I was most afraid of πŸ™‚.

So to summarize @pnp/cli-for-microsoft-365-maintainers I would like to kindly ask you to help me/us pick the best naming here. If I understood the comments correctly we have the following options (@milanholemans please edit my post if I missed something πŸ™‚):

  • m365 spfx project azdo pipeline add
  • m365 spfx project azuredevops pipeline add
  • m365 spfx project devops pipeline add
  • m365 spfx project azure pipeline add

What option would you pick best? Please feel free to go over the above posts to check maybe some of the pros and cons that we had for each of those along the way πŸ™‚

Adam-it avatar Jan 09 '24 23:01 Adam-it

I suggest we don't use devops because it's a generic term that doesn't represent a specific tool in the broader ecosystem. If all you use is Azure DevOps, then yes, it's clear, but what if you only use GitHub or some other tool? devops is ambiguous and we should avoid it.

I'm perfectly fine with azdo as many folks internally at Microsoft use it, so I'm used to it. That said, it would be interesting to learn if it resonates with the broader ecosystem.

Have we considered azure (equivalent to GitHub) as an option?

waldekmastykarz avatar Jan 10 '24 07:01 waldekmastykarz