Azure / static-web-apps

Azure Static Web Apps. For bugs and feature requests, please create an issue in this repo. For community discussions, latest updates, kindly refer to the Discussions Tab. To know what's new in Static Web Apps, visit https://aka.ms/swa/ThisMonth
https://aka.ms/swa
MIT License
330 stars 56 forks source link

DocFx + Azure DevOps + pipeline #367

Closed patware closed 3 years ago

patware commented 3 years ago

It's great to see Azure DevOps (other) as a source.

I have a docFx documentation that I want to push to an Azure Static Web App, but the pipeline fails and I can't figure how to solve the problem. This looks a lot like issue #351.

Digest: sha256:d33e14983d8db3c4440855d6755524a46d1d4a67968b6e2c47264a4ff859d014 Status: Downloaded newer image for mcr.microsoft.com/appsvc/staticappsclient:stable DeploymentId: 092406ab-85ba-4691-8098-d28a8cbc9ca3

App Directory Location: '/doc/_site' is invalid. Could not detect this directory. Please verify your workflow reflects your repository structure.

For further information, please visit the Azure Static Web Apps documentation at https://docs.microsoft.com/en-us/azure/static-web-apps/ If you believe this behavior is unexpected, please raise a GitHub issue at https://github.com/azure/static-web-apps/issues/ Exiting

Finishing: AzureStaticWebApp

git repo: The documentation in the repo is under: /doc/

Pipeline runs in 2 stages.

Stage 1:

Stage 2:

The generated site files are generated and available in the artifacts. I see the index.html for example.

Note for the MS documentators: The DocFx task seems to require a Windows agent, while the AzureStaticWebApp task seems to require a Ubuntu agent.

name: $(Date:yyyyMMdd)$(Rev:.r)

trigger:
  branches:
    include:
      - main

stages:
  - stage: Build
    displayName: Build the doc
    pool:
      vmImage: 'windows-latest'
    jobs:
      - job: 
        displayName: Build
        steps:

          - task: DocFxTask@0
            displayName: DocFx
            inputs:
              solution: 'doc\docfx.json'

          - task: CopyFiles@2
            displayName: Copy generated site to staging directory
            inputs:
              SourceFolder: '$(Build.SourcesDirectory)\doc\_site'
              Contents: '**'
              TargetFolder: '$(Build.ArtifactStagingDirectory)'
              CleanTargetFolder: true

          - publish: $(Build.ArtifactStagingDirectory)
            displayName: Publish Artifacts
            artifact: Docs

  - stage: Deploy
    dependsOn: Build
    displayName: Deploy to Azure
    pool:
      vmImage: 'ubuntu-latest'
    jobs:
    - job:
      steps:
        - task: AzureStaticWebApp@0
          inputs:
           app_location: "/doc/_site"
          env:
            azure_static_web_apps_api_token: $(deployment_token)

For the AzureStaticWebApp task, I tried various combinations.

- task: AzureStaticWebApp@0
  inputs:
   app_location: $(Build.ArtifactStagingDirectory)
   output_location: ""
  env:
    azure_static_web_apps_api_token: $(deployment_token)
- task: AzureStaticWebApp@0
  inputs:
   app_location: $(Build.ArtifactStagingDirectory)
  env:
    azure_static_web_apps_api_token: $(deployment_token)
- task: AzureStaticWebApp@0
  inputs:
    app_location: "/doc"
    output_location: "_site"
  env:
    azure_static_web_apps_api_token: $(deployment_token)
anthonychu commented 3 years ago

Do you need to download the artifacts in the second stage?

Can you add an inline script task before the Static Web Apps task with ls to confirm the directory contents?

patware commented 3 years ago

Hi,

I'm half way in transitionning from build+release to multi-stage pipeline. The publish artifact is only for the release. As soon as I'm done with the Static Web App part, I'll finish the transition to multi-stage.

Looking at the build results, the "artifacts" link shows the expected files.

'$(Build.SourcesDirectory)\doc\_site'

I can add an ls command if it makes sense.

patware commented 3 years ago

HAaa I'm dumb !

stage 1 runs on a windows agent, stage 2 runs a on a ubuntu agent, of course the files from stage 1 can't magically appear in stage 2 (two different machines).

So stage 2 starts with a Initialize job, then Checkout main branch, and so on..

Let me try a few things ;)

patware commented 3 years ago

Close but no cigar...

Stage 2 now starts with task:

- task: DownloadPipelineArtifact@2

The ls -R, with workingDirectory: $(Pipeline.Workspace) shows the expected files:

Generating script.
Script contents:
ls -R
========================== Starting Command Output ===========================
[command]/usr/bin/bash --noprofile --norc /home/vsts/work/_temp/83a490f4-ea4a-4e58-8577-6f7d0dd84067.sh
.:
Docs
TestResults
a
b
s

./Docs:
Readme.html
Release-Notes
agentSoftwareVersion.html
devops.productfamilies.html
favicon.ico
fonts
images
index.html
index.json
libraries
logo.svg
manifest.json
search-stopwords.json
styles
tfs2015migration
toc.html
xrefmap.yml

The "Docs" folder is the published artifact name, from stage 1.

Then, I tried these 3:

        - task: AzureStaticWebApp@0
          inputs:
           app_location: $(Pipeline.Workspace)
          env:
            azure_static_web_apps_api_token: $(deployment_token)

App Directory Location: '/home/vsts/work/1' is invalid. Could not detect this directory. Please verify your workflow reflects your repository structure.

This was expected. Was missing the "/Docs"

Try 2:


        - task: AzureStaticWebApp@0
          inputs:
           app_location: $(Pipeline.Workspace)
           output_location: Docs
          env:
            azure_static_web_apps_api_token: $(deployment_token)

App Directory Location: '/home/vsts/work/1' is invalid. Could not detect this directory. Please verify your workflow reflects your repository structure.

and 3:

        - task: AzureStaticWebApp@0
          inputs:
           app_location: "$(Pipeline.Workspace)/Docs"
          env:
            azure_static_web_apps_api_token: $(deployment_token)

App Directory Location: '/home/vsts/work/1/Docs' is invalid. Could not detect this directory. Please verify your workflow reflects your repository structure.

Last check before calling it a night:

I changed the script to pwd && ls -R

========================== Starting Command Output ===========================
/usr/bin/bash --noprofile --norc /home/vsts/work/_temp/0ad28d46-7ae0-4cd3-83eb-9890e071c40b.sh
/home/vsts/work/1
.:
Docs
TestResults
a
b
s

./Docs:
Readme.html
Release-Notes
agentSoftwareVersion.html
devops.productfamilies.html
favicon.ico
fonts
images
index.html
index.json
libraries
logo.svg
manifest.json
search-stopwords.json
styles
tfs2015migration
toc.html
xrefmap.yml

Log says: App Directory Location: '/home/vsts/work/1/Docs' is invalid

And we can see from the pwd + ls that the folder exists

Opinion/comment

Call me old school or close minded, but static web sites should be the easiest type of web app to deploy. They're static, nothing to compile, interpret or generate. 1 file in, 1 file out.

If something has to generate the "static web site", that something should be a task we execute prior to that.

I see from the MS Docs that we can use Gatsby, Hugo, VuePress or Jekyll to publish from a static site generator, or Blazor, Next.js and Nuxt.js to Deploy from a framework. I don't know these, I've heard the terms but never had the time to learn more. But from my understanding, they all start with some bootstrapping, config, setup and/or, recipe. Then a tool runs that generates the actual web files. And those generated files are the ones that are published to the Azure Static Web App resource.

Source + tooling => generated => Azure Static Web App

To me, Source + tooling => generated is pretty much the equivalent of a build.

Suggestion

Just like Docker task, add a "Command" parameter.

(Required) Possible values: buildAndPush, build, push, login, logout Added in version 2.173.0: start, stop Default value: buildAndPush

If I don't need to build anything, I choose

inputs:
  command: push
  sourceFolder: $(Pipeline.Workspace) # or whatever
  azure_static_web_apps_api_token: $(deployment_token)

If I need to build and push

inputs:
  command: buildPush
  app_location: "/app"
  output_location: "build"
  azure_static_web_apps_api_token: $(deployment_token)

Etc.

anthonychu commented 3 years ago

You've hit a problem that others have run into as well. app_location (and api_location) are relative to the workspace directory, this means that it should simply be:

        - task: AzureStaticWebApp@0
          inputs:
           app_location: Docs
          env:
            azure_static_web_apps_api_token: $(deployment_token)

We're learning that this is unintuitive for Azure DevOps customers, who are used to prepending $(Pipeline.Workspace) and similar variables to build an absolute path. We'll investigate what we can do here to make this consistent with other tasks.

Thanks for the feedback. We plan on accepting azure_static_web_apps_api_token as an input to the task. If there's nothing to build, the task will simply perform a deployment of the files in the app location.

patware commented 3 years ago

Thanks for the quick feedback, I just tried your recommendation but got the same error. Since I'm sure that the folder exists, that there are files there, I suspect that I'm missing something.

I think I found the rock in the shoe: staticwebapp.config.json I don't have one. I'll add one, try and share the results here.

Suggestion 1 - task logging improvements

Add more output to the output logs.

App Directory Location: 'Docs' is invalid. Could not detect this directory. Please verify your workflow reflects your repository structure.

Not sure why Docs is invalid or what "detect" is. I would like to see "looking for xyz", "looked in this location" etc.

Suggestion 2 - Docs improvement

Include a vanilla index.html web site sample in the docs.

And since DocFx is picking up interest (well it seems like that anyway), an example with a DocFx.

patware commented 3 years ago

It wasn't the missing staticwebapp.config.json.

anthonychu commented 3 years ago

Agreed about the logging. In this case it would be helpful to show the directory and list its contents we can see what the task is seeing. @miwebst

We need to troubleshoot this some more. Perhaps @smurawski has some ideas.

smurawski commented 3 years ago

My only thought is that either the task should support full paths or you should be able to specify where you want the task to be executed from.

For example, (this may be fixed now, but was a problem at one point) Download Pipeline Artifact and Download Build Artifact went to different places in the file system.

patware commented 3 years ago

If it makes sense, contact me directly and we could arrange a shared desktop session, ex: MS Teams.

My feeling is that it's a simple fix, something that will be obvious once found.

patware commented 3 years ago

Is there something I can do ?

jromal commented 3 years ago

If you call your artifact 'Docs', try downloading the artifact to '$(Build.SourcesDirectory)/Docs' and then set '/Docs' as app_location. In my case was the combination that worked. I found the idea here but I do not have the link anymore.

patware commented 3 years ago

OMG... it worked. Thank you @javier-romera

        - task: DownloadPipelineArtifact@2
          inputs:
            buildType: 'current'
            targetPath: '$(Build.SourcesDirectory)'

        - task: AzureStaticWebApp@0
          enabled: true
          continueOnError: true
          inputs:
           app_location: "/Docs"
          env:
            azure_static_web_apps_api_token: $(deployment_token)

The trick was the "$(Build.SourcesDirectory)". The AzureStaticWebApp's actions seems to be relative to the sourceDirectory.

@anthonychu I have a few recommendations:

  1. document how the task works, what the arguments the mcr.microsoft.com/appsvc/staticappsclient expects and what the task sets these arguments.
  2. document the docfx scenario or redirect the user to another way of hosting docfx generated sites if it makes more sense
  3. make the task docfx friendly

Thank you everyone, you've allowed me to progress and move on to better things :)

anthonychu commented 3 years ago

We’ve had some great feedback, including in this thread, on some improvements we can make on how to improve the task for Azure DevOps. We’ll also work on better documenting the task. Most likely we’ll align the inputs with the GitHub Action and document them together.

As for DocFX, we’ll look into supporting it if we see more demand for it. Feel free to create an issue requesting built-in support.

klacol commented 2 years ago

Hi, nice post here. I just wanted to share my solution with DocFx. I use the action nikeee/docfx-action@v1.0.0 and it works quite well:

jobs:
  build_and_deploy docfx:
      runs-on: ubuntu-latest
      name: Build DocFx project and generate static site
      steps:
      - uses: actions/checkout@v2
      - uses: nikeee/docfx-action@v1.0.0
        name: Build Documentation
        with:
          args: docs/docfx_project/docfx.json
    - name: Build And Deploy to Azure static web
      id: builddeploy
      uses: Azure/static-web-apps-deploy@v1
      with:
        azure_static_web_apps_api_token: ${{ secrets.ABC }}
        repo_token: ${{ secrets.GITHUB_TOKEN }} 
        action: "upload"
        app_location: "/docs/docfx_project/_site" 

The thing I am struggling with is, how to protect the site only to Azure Active Directory accounts.