Setup Pipeline for SPFx library – PnP Search Extensibility Library

Ahamed Fazil Buhari
 
Senior Developer
April 27, 2021
 
Rate this article
 
Views
1546

If we want to deploy an SPFx webpart or extension which uses SPFx library components, then we need to handle this differently while we need to bundle and package our webpart or extension.

According to MS doc for SPFx Library component, if we want to use the library in other solution (webpart or extension) then we need to do npm link to the root directory of the library solution and run npm link <library-name> in the solution (webpart or extension) that will create symbolic link to the webpart. If we want to handle this build process in a pipeline with a symbolic link then you can refer below YML,

For this blog, let’s take PnP Modern Search v4 as an example. In v4 there is a possibility to make an extensibility library that is used for custom render.

You can download latest PnP Moder Search sppkg from here, select latest release and at the bottom you can find files that contains .sppkg

pnp sppkg

Below you can find the folder structure that’s used to deploy PnP Search Extensibility library in our site,

pnpcustomlibraryfolder

azure-pipeline.yml for the above solution,

trigger:
  branches:
    include:
      - master
      - develop
      - release/*
      - feature/*
steps:
  - checkout: self
  - task: NodeTool@0
    displayName: 'Use Node 10.x'
    inputs:
      versionSpec: 10.x
      checkLatest: true
  #region Install and bundle lib
  - task: Npm@1
    displayName: "npm install search-extensibility"
    inputs:
      command: "install"
      workingDir: "search-extensibility/"

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

  - script: npm link
    displayName: "npm link"
    workingDirectory: "search-extensibility/"

  - task: Npm@1
    displayName: "npm install search-result-customlibrary"
    inputs:
      command: "install"
      workingDir: "search-result-customlibrary/"
    continueOnError: false

  - script: npm link @pnp/modern-search-extensibility
    displayName: "npm link @pnp/modern-search-extensibility"
    workingDirectory: "search-result-customlibrary/"

  - task: Gulp@0
    displayName: "Bundle project"
    inputs:
      gulpFile: search-result-customlibrary/gulpfile.js
      targets: bundle
      arguments: "--ship"
      workingDirectory: "search-result-customlibrary"

  - task: Gulp@0
    displayName: "Package Solution"
    inputs:
      gulpFile: search-result-customlibrary/gulpfile.js
      targets: "package-solution"
      arguments: "--ship"
      workingDirectory: "search-result-customlibrary"

  - task: CopyFiles@2
    displayName: "Copy Files to drop"
    inputs:
      Contents: |
        search-result-customlibrary/sharepoint/**/*.sppkg
      TargetFolder: "$(Build.ArtifactStagingDirectory)"

  - task: CopyFiles@2
    displayName: 'Copy PnP sppkg to drop'
    inputs:
      Contents: |
        pnp-package/*.sppkg
      TargetFolder: '$(Build.ArtifactStagingDirectory)/sharepoint'

  #endregion

  - task: PublishBuildArtifacts@1
    displayName: 'Publish Artifact: drop'

These are the tasks that will be executed if we run above yml,

 

And the output of the published files looks from build pipeline will be like this,

 

Now we successfully generated sppkg’s for our custom library through build pipeline, the next step is to deploy this in release pipeline. The below powershell can be helpful to deploy the solution (please ignore the $env variable and change those according to your need),

try {
    $clientId = $env:SPO_AppID
    $clientSecret = $env:SPO_AppSecret
    $spoUrl = "https://tenantName.sharepoint.com"

    $pnpSearchWebpartFileName = "$(System.ArtifactsDirectory)$(ArtifactAlias)dropsharepointpnp-packagepnp-modern-search-parts-v4.sppkg"
    $pnpSearchExtensibilityFileName = "$(System.ArtifactsDirectory)$(ArtifactAlias)dropsharepointpnp-packagepnp-modern-search-extensibility.sppkg"
    $customSearchLibraryFileName = Get-ChildItem -Path '$(System.ArtifactsDirectory)$(ArtifactAlias)dropsearch-result-customlibrarysharepointsolution' -Recurse | Where-Object { $_.PSIsContainer -eq $false -and $_.Extension -eq '.sppkg' }    

    Write-Host "PnP Connection to $spoUrl" -ForegroundColor Yellow
    Connect-PnPOnline -Url $spoUrl -ClientId $clientId -ClientSecret $clientSecret
    Write-Host "Successfully connected" -ForegroundColor Green

    #region Installing PnP Search WebPart
    Write-Host "Installing PnP Search WebPart" -ForegroundColor Green
    $appMetadata = Add-PnPApp $pnpSearchWebpartFileName -Overwrite -Publish
    $appId = $appMetadata.Id
    Write-Host "Package ID: $appId" 
    Write-Host "Added PnP Search WebPart - DONE" -ForegroundColor Green
    #endregion

    #region Installing PnP Search Extensibility
    Write-Host "Installing PnP Search Extensibility" -ForegroundColor Green
    $appMetadata = Add-PnPApp $pnpSearchExtensibilityFileName -Scope Tenant -Overwrite -Publish -SkipFeatureDeployment
    $appId = $appMetadata.Id
    Write-Host "Package ID: $appId" 
    Write-Host "Added PnP Search Extensibility - DONE" -ForegroundColor Green

    $existingApp = Get-PnPApp -Identity $appId -Scope Tenant
    if ($null -ne $existingApp) {
        write-host "Start: Update-PnPApp -Identity $appId"
        Update-PnPApp -Identity $appId -Scope Tenant
    }
    else {
        write-host "No installed app found"
        write-host "Start Install-PnPApp -Identity $appId"
        Install-PnPApp -Identity $appId -Scope Tenant
    }

    write-host "Publish-PnPApp -Identity $appId"
    Publish-PnPApp -Identity $appId -Scope Tenant
    Write-Host "Installing PnP Search Extensibility - DONE" -ForegroundColor Green
    #endregion

    #region Installing PnP Search Custom Library
    Write-Host "Installing PnP Search Custom Library" -ForegroundColor Green
    $appMetadata = Add-PnPApp $customSearchLibraryFileName.FullName -Scope Tenant -Overwrite -Publish -SkipFeatureDeployment
    $appId = $appMetadata.Id
    Write-Host "Package ID: $appId" 

    $existingApp = Get-PnPApp -Identity $appId -Scope Tenant
    if ($null -ne $existingApp) {
        write-host "Start: Update-PnPApp -Identity $appId -Scope Tenant"
        Update-PnPApp -Identity $appId -Scope Tenant
    }
    else {
        write-host "No installed app found"
        write-host "Start Install-PnPApp -Identity $appId -Scope Tenant"
        Install-PnPApp -Identity $appId -Scope Tenant
    }
    write-host "Publish-PnPApp -Identity $appId"
    Publish-PnPApp -Identity $appId -Scope Tenant
    Write-Host "Installing PnP Search Custom Library - DONE" -ForegroundColor Green
    #endregion
}
catch {
    Write-Host -f Red "Error while installing PnP search webpart & libraries! - " $_.Exception.Message
}

Below is the screenshot from release pipeline,

Happy Coding

Fazil

Author Info

Ahamed Fazil Buhari
 
Senior Developer
 
Rate this article
 
Ahamed is a Senior Developer and he has very good experience in the field of Microsoft Technologies, especially SharePoint, Azure, M365, SPFx, .NET and client side scripting - JavaScript, TypeScript, ...read more
 

Leave a comment