Download Azure Icons #309
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Download Azure Icons | |
on: | |
schedule: | |
- cron: '12 3 * * *' | |
workflow_dispatch: | |
jobs: | |
download: | |
runs-on: ubuntu-latest | |
name: Download | |
outputs: | |
confighash: ${{ steps.src.outputs.confighash }} | |
pageversion: ${{ steps.src.outputs.pageversion }} | |
steps: | |
- name: Set up Python | |
uses: actions/setup-python@v5 | |
with: | |
python-version: 3.8 | |
- id: src | |
name: Download sources | |
shell: pwsh | |
run: | | |
# Azure Portal config | |
$portalconfig=if((irm "https://portal.azure.com/") -match 'MsPortalImpl\.redirect\(([^)]+)\)'){$matches[1]|convertfrom-json}else{throw} | |
$portalconfighash=$portalconfig.portalServerConfig.portalQuery.configHash | |
"confighash=$portalconfighash" >> $env:GITHUB_OUTPUT | |
$portalconfigpageversion=$portalconfig.portalServerConfig.portalQuery.pageVersion | |
"pageversion=$portalconfigpageversion" >> $env:GITHUB_OUTPUT | |
"Downloading from Azure Portal version $portalconfigpageversion with config hash $portalconfighash" >> $env:GITHUB_STEP_SUMMARY | |
# Requires config | |
$portalrequiresfile=if((irm "https://portal.azure.com/?configHash=$portalconfighash&pageVersion=$portalconfigpageversion") -match '"/Content/PortalRequireConfig/([^"]+)"'){$matches[1]}else{throw} | |
$portalrequires=if((irm "https://portal.azure.com/Content/PortalRequireConfig/$portalrequiresfile") -match 'MsPortalImpl\.setRequireConfig\(([^)]+)\)'){$matches[1]|convertfrom-json}else{throw} | |
# Icon Styles CSS | |
$portalcssfile=($portalrequires.requireConfig.dependencyTree.psobject.properties|?{$_.value.psobject.properties.name -contains '_generated/Less/MsPortalImpl/Base/Base.Images.css'}).name | |
$iconstyles=if((irm "https://portal.azure.com/$($portalcssfile).js") -match 'define\("_generated/Less/MsPortalImpl/Base/Base\.Images\.css".*return{css:"([^"]+)"'){$matches[1]}else{throw} | |
$iconstyles|out-file icon-styles.css -nonewline | |
# Image Library JSON | |
$imagelibraryfile=($portalrequires.requireConfig.dependencyTree.psobject.properties|?{$_.value.psobject.properties.name -contains 'MsPortalImpl/Base/Base.ImageLibrary'}).name | |
$imagelibraryjs=irm "https://portal.azure.com/$($imagelibraryfile).js" | |
$imagelibrary=([regex]'{type:(\d+),data:"(<svg[^"]+</svg>)"}').matches($imagelibraryjs)|select @{n='type';e={[int]($_.groups[1].value)}},@{n='svg';e={$_.groups[2].value}} | |
$svglibrary=$portalrequires.requireConfig.dependencyTree.psobject.properties|?{$_.value.psobject.properties.name -like '*.svg'}|select -exp name|sort-object -unique|%{([regex]'{type:(\d+),data:"(<svg[^"]+</svg>)"}').matches((irm "https://portal.azure.com/$($_).js"))|select @{n='type';e={[int]($_.groups[1].value)}},@{n='svg';e={$_.groups[2].value}}} | |
$iconlibrary=$imagelibrary+$svglibrary | |
$iconlibrary|convertto-json -depth 100|out-file icon-library.json | |
"Got total of $($iconlibrary.count) library icons" >> $env:GITHUB_STEP_SUMMARY | |
# Icon Assets JSON | |
$manifestindex=$portalconfig.portalServerConfig.supportedLanguages.IndexOf('en') | |
$manifesthash=$portalconfig.portalServerConfig.environment.extensionsManifestHash.assetTypes[$manifestindex][0] | |
$iconassets=(irm "https://portal.azure.com/Content/ExtensionManifest/$manifesthash.json").manifest | |
$iconassets|convertto-json -depth 100|out-file icon-assets.json | |
"Got total of $($iconassets.psobject.properties.value.count) manifests and $($iconassets.psobject.properties.value.assettypes.count) assets" >> $env:GITHUB_STEP_SUMMARY | |
- id: upload-src | |
name: Save sources | |
uses: actions/upload-artifact@v4 | |
with: | |
name: src | |
compression-level: 9 | |
path: | | |
icon-styles.css | |
icon-library.json | |
icon-assets.json | |
- name: Convert sources to icon data | |
shell: pwsh | |
run: | | |
$iconstyles=gc icon-styles.css -raw | |
$iconlibrary=gc icon-library.json|convertfrom-json | |
$iconassets=gc icon-assets.json|convertfrom-json | |
$iconlibraryhashtable=$iconlibrary|%{$ht=@{}}{$ht[[int]$_.type]=$_.svg}{$ht} | |
$icondata=$iconassets.psobject.properties|?{$_.value.assetTypes}|%{ | |
$m=$_.name | |
$_.value.assetTypes|?{$_.icon.length -gt 0}|%{ | |
$firsticon=$null | |
$firsticon=$_.icon[0] | |
$firsticontype=[int]$firsticon.type | |
if($firsticon.data -like '<svg*'){ | |
$svg=$firsticon.data | |
}elseif($firsticontype -gt 1 -and $iconlibraryhashtable.contains($firsticontype)){ | |
$svg=$iconlibraryhashtable[$firsticontype] | |
}else{ | |
$svg='<svg viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg"><text x="0" y="25" class="small">'+$firsticontype+'</text></svg>' | |
} | |
$svg=$svg -replace "xmlns:svg='http://www.w3.org/2000/svg'","xmlns='http://www.w3.org/2000/svg'" | |
$svg=$svg -replace '</svg>',"<style>$iconstyles</style></svg>" | |
$svg=$svg -replace '<title></title>',"<title>$([web.httputility]::htmlencode(($_.singularDisplayName -replace "`n",'')))</title><desc>$([web.httputility]::htmlencode(($_.description -replace "`n",' ')))</desc>" | |
[pscustomobject]@{ | |
name="$($m)/$($_.name)" | |
svg=$svg | |
singularDisplayName=$_.singularDisplayName -replace "`n",'' | |
pluralDisplayName=$_.pluralDisplayName -replace "`n",'' | |
resourceType=$_.resourceType.resourceTypeName -replace "`n",'' | |
keywords=$_.keywords -replace "`n",' ' | |
description=$_.description -replace "`n",' ' | |
} | |
} | |
} | |
"Resolved $($icondata.count) icons" >> $env:GITHUB_STEP_SUMMARY | |
$icondata|convertto-json -depth 100|out-file icon-data.json | |
- id: upload-data | |
name: Upload icon data | |
uses: actions/upload-artifact@v4 | |
with: | |
name: data | |
compression-level: 9 | |
path: icon-data.json | |
- name: Save SVG icons | |
shell: pwsh | |
run: | | |
$icondata=gc icon-data.json|convertfrom-json | |
new-item -itemtype directory -name svg|out-null | |
$iconstat=$icondata|%{$_.svg|new-item -path "svg/$($_.name).svg" -force}|measure-object -property length -sum | |
"Created $($iconstat.count) svg files with total size $([math]::round($iconstat.sum/1024/1024, 1))MB" | |
- name: Export Draw.io shape library | |
run: | | |
pip install drawio-svg-library | |
mkdir drawio | |
drawio-svg-library $(find . -name "*.svg") --output "drawio/Azure portal icons.xml" | |
- name: Compose HTML | |
shell: pwsh | |
run: | | |
$icondata=gc icon-data.json|convertfrom-json | |
$html=$icondata|% ` | |
{"<html><head><meta name=`"viewport`" content=`"width=device-width, initial-scale=1`"><title>Azure Icons</title><style>body{margin:0}table,th,td{border:1px solid #CCCCCC;border-collapse:collapse;padding:3px}tbody{word-break:break-all;}thead,tfoot{position:sticky;}thead{inset-block-start:0;background-color:#CCCCCC}tfoot{inset-block-end:0;background-color:#CCCCCC}a:link,a:visited,a:hover{color:black}a:active{color:blue}</style><script>function download(uri, name){const a=document.createElement(`"a`");a.href=uri;a.download=name+`".svg`";a.click();}</script></head><body><table><thead><tr><th scope=`"col`" style=`"width: 10%`">Click to download</th><th scope=`"col`" style=`"width: 20%`">Name</th><th scope=`"col`" style=`"width: 20%`">Type</th><th scope=`"col`" style=`"width: 20%`">Keywords</th><th scope=`"col`" style=`"width: 30%`">Description</th></tr></thead><tbody>"} ` | |
{"<tr title=`"$($_.name)`"><td><img loading=`"lazy`" decoding=`"async`" src=`"svg/$($_.name).svg`" alt=`"$($_.singularDisplayName)`" title=`"Click to download`" onclick=`"download(this.src, this.alt)`" /></td><td>$($_.singularDisplayName)</td><td>$($_.resourceType)</td><td>$($_.keywords)</td><td>$($_.description)</td></tr>"} ` | |
{"</tbody><tfoot><tr><td colspan=`"5`">Extracted from Azure Portal version ${{ steps.src.outputs.pageversion }} on $(get-date -f 'yyyy-MM-dd'). Icons <a target=`"_blank`" href=`"https://www.microsoft.com/en-us/legal/intellectualproperty/copyright/permissions`">used with permission from Microsoft</a>. Source on <a target=`"_blank`" href=`"https://github.com/maskati/azure-icons`">GitHub</a>.</td></tr></tfoot></table></body></html>"}|out-string | |
$html|out-file index.html | |
"Created HTML of $([math]::round((gi index.html).length/1024/1024, 1))MB" >> $env:GITHUB_STEP_SUMMARY | |
- id: upload-azure-icons | |
name: Upload Azure Icons | |
uses: actions/upload-artifact@v4 | |
with: | |
name: azure-icons | |
compression-level: 9 | |
path: | | |
svg/ | |
drawio/ | |
index.html | |
- name: Compose Markdown | |
shell: pwsh | |
run: | | |
$icondata=gc icon-data.json|convertfrom-json | |
$markdown=$icondata|% ` | |
{"# Azure Icons`n`nExtracted from Azure Portal version ${{ steps.src.outputs.pageversion }} on $(get-date -f 'yyyy-MM-dd').`n`nIcons [used with permission from Microsoft](https://www.microsoft.com/en-us/legal/intellectualproperty/copyright/permissions).`n`n| Icon | Type |`n| --- | --- |"} ` | |
{"| [$($_.singularDisplayName -replace '\[|\]|\|','')](svg/$($_.name).svg) | $($_.resourceType -replace '/','/ ') |"} ` | |
{""}|out-string | |
$markdown|out-file README.md | |
"Created Markdown of $([math]::round((gi README.md).length/1024/1024, 1))MB" >> $env:GITHUB_STEP_SUMMARY | |
- name: Upload Markdown | |
uses: actions/upload-artifact@v4 | |
with: | |
name: markdown | |
compression-level: 9 | |
path: README.md | |
commit: | |
runs-on: ubuntu-22.04 | |
name: Commit | |
permissions: | |
actions: write # required for workflow_dispatch | |
contents: write # required for git push | |
needs: download | |
steps: | |
- name: Git checkout | |
uses: actions/checkout@v4 | |
- name: Download Azure Icons | |
uses: actions/download-artifact@v4 | |
with: | |
name: azure-icons | |
path: . | |
- name: Download markdown | |
uses: actions/download-artifact@v4 | |
with: | |
name: markdown | |
path: . | |
- name: Git config as workflow | |
run: | | |
git config user.name "GitHub Actions (${{ github.workflow }})" | |
git config user.email "<>" | |
- name: Git add and commit if changed | |
run: | | |
git add svg/* | |
git add index.html | |
git add README.md | |
git add drawio/* | |
git diff-index --quiet HEAD || git commit -m 'Update to version ${{ needs.download.outputs.pageversion }}' | |
- name: Git push | |
run: | | |
git push origin main | |
- name: Trigger publish | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
github.rest.actions.createWorkflowDispatch({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
workflow_id: 'static.yml', | |
ref: 'main', | |
}) |