Sharepoint - Upload Master Page / Page Layouts using PowerShell

Option 1

How to add/upload publishing page layout via CSOM in PowerShell:

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")


Function Get-ClientContext([string]$Url,[string]$UserName,[string]$Password)
{
    $SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
    $context = New-Object Microsoft.SharePoint.Client.ClientContext($Url)
    $context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
    return $context
}



Function Deploy-PageLayout([Microsoft.SharePoint.Client.Web]$Web,[string]$FilePath,[string]$AssociatedContentTypeId)
{
     $pageLayoutContentTypeId = "0x01010007FF3E057FA8AB4AA42FCB67B453FFC100E214EEE741181F4E9F7ACC43278EE8110003D357F861E29844953D5CAA1D4D8A3B001EC1BD45392B7A458874C52A24C9F70B"
     $fileName = [System.IO.Path]::GetFileName($FilePath)

     $associatedContentType = $Web.AvailableContentTypes.GetById($AssociatedContentTypeId)
     $catalogList = $Web.GetCatalog([Microsoft.SharePoint.Client.ListTemplateType]::MasterPageCatalog)    
     $Web.Context.Load($catalogList.RootFolder)
     $Web.Context.Load($associatedContentType)
     $Web.Context.ExecuteQuery()



     $fileContent = [System.IO.File]::ReadAllBytes($FilePath)
     $fileInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
     $fileInfo.Content = $fileContent
     $fileInfo.Url = $catalogList.RootFolder.ServerRelativeUrl + "/" + $fileName
     $fileInfo.Overwrite = $true

     $file = $catalogList.RootFolder.Files.Add($fileInfo)
     $Web.Context.Load($file)
     $Web.Context.ExecuteQuery()

     $listItem = $file.ListItemAllFields
     #listItem["Title"] = title;
     #listItem["MasterPageDescription"] = description;
     $listItem["ContentTypeId"] = $pageLayoutContentTypeId
     $listItem["PublishingAssociatedContentType"] = [string]::Format(";#{0};#{1};#", $associatedContentType.Name, $associatedContentType.Id.StringValue)
     $listItem["UIVersion"] = [Convert]::ToString(15)
     $listItem.Update()

     $Web.Context.ExecuteQuery()
}


$UserName = "[email protected]"
$Password = Read-Host -Prompt "Enter the password"    
$Url = "https://contoso.sharepoint.com/"

$WelcomePageContentTypeId = "0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF390064DEA0F50FC8C147B0B6EA0636C4A7D4"
$WelcomePageFilePath = "C:\Assets\ContosoBlankWebPartPage.aspx"


$context = Get-ClientContext -Url $Url -UserName $UserName -Password $Password
Deploy-PageLayout -Web $context.Web -FilePath $WelcomePageFilePath -AssociatedContentTypeId $WelcomePageContentTypeId
$context.Dispose()

Option 2

You could utilize PowerShell cmdlets from PnP project, in particular Add-SPOPublishingPageLayout command.