Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong path when resolving absolute file paths in Azure Pipelines #220

Closed
bryanbcook opened this issue Sep 30, 2023 · 5 comments · Fixed by #221
Closed

Wrong path when resolving absolute file paths in Azure Pipelines #220

bryanbcook opened this issue Sep 30, 2023 · 5 comments · Fixed by #221

Comments

@bryanbcook
Copy link

bryanbcook commented Sep 30, 2023

First off, awesome job adding support for Azure Pipelines!

I am attempting to understand how you're parsing azure-pipelines so that I could potentially write unit tests or validate YAML formatting locally before committing. My team uses templates extensively, so minor malformed files are a huge problem.

I'm not 100% convinced I'm doing something wrong with the Context

Expected:

  • Files that start with / should be resolved from the root of the repository. (eg /<path>/<to>/<template>.yml)
  • Files that do not start with / should be resolved relative to the current template. (eg <file>.yml, ../<relative-path>.yml)

Actual:

  • Files that start with / are resolved relative to the current file.

Steps to Reproduce:

I have an azure pipeline with the following simplified folder structure:

/devops/pipelines/microservices/service1/pipeline.yml
/devops/pipelines/microservices/service1/variables.yml
/devops/pipelines/templates/jobs/microservice-ci.yml

The pipeline has issues resolving the variables.yml file.

# pipeline.yml

trigger: none

variables:
- template: variables.yml

stages:
- stage: one
  jobs:
   - template: /devops/pipelines/templates/jobs/microservice-ci.yml

My code to test loading the pipeline:

using GitHub.DistributedTask.Expressions2;
using GitHub.DistributedTask.ObjectTemplating;
using Runner.Server.Azure.Devops;
using System;
using System.Collections.Generic;
using Xunit;

public class Fixture
{
   [Fact]
   public void CanLoadRootedTemplate()
   {
      var cwd = @"c:\code\myrepo";
      var fileRelativePath = "devops/pipelines/microservices/service1/pipeline.yml";

      var context = new Runner.Server.AzureDevops.Context
      {
         FileProvider = new LocalFileProvider(cwd),
         TraceWriter = new EmptyTraceWriter(),
         VariablesProvider = new TestVariablesProvider(),
         Flags = ExpressionFlags.DTExpressionsV1 | ExpressionFlags.ExtendedDirectives
      };

      var evaluatedRoot = AzureDevops.ReadTemplate(context, fileRelativePath, null);
      var pipeline = new Pipeline().Parse( context.ChildContext( evaluatedRoot, fileRelativePath), evaluatedRoot);
    }
}

class LocalFileProvider : IFileProvider
{
     private string cwd;

     public LocalFileProvider(string cwd)
     {
         this.cwd = cwd;
     }
     
     public string ReadFile(string repositoryAndRef, string path)
     {
         var filePath = System.IO.Path.Combine( cwd, path);
         return System.IO.File.ReadAllText( filePath );
     }
}

class TestVariablesProvider : IVariablesProvider
{
    public IDictionary<string,string> GetVariablesForEnvironment(string name = null)
    {
        return new Dictionary<string,string>(StringComparer.OrdinalIgnoreCase);
    }
}

The test fails with System.IO.DirectoryNotFoundException : Could not find a part of the path 'c:\code\myrepo\devops\pipelines\microservices\service1\devops\pipelines\templates\jobs\microservice-ci.yml'

bryanbcook added a commit to bryanbcook/runner.server that referenced this issue Sep 30, 2023
@ChristopherHX
Copy link
Owner

Thank you for reporting this bug, indeed my current code doesn't handle absolute paths at all.

Microsoft should improve their azure pipelines docs, because of this I didn't even know that you can reference local templates via absolute paths.

For example
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops&pivots=templates-includes#reference-template-paths

mentions any variations of relative paths, but no single absolute path is shown.

Just parsing a template via my code would skip validation of $[], conditions and potential other things, but yes thats how far you can go with unit testing.

@bryanbcook
Copy link
Author

I submitted MicrosoftDocs/azure-devops-docs#13674 to update the documentation.

Just parsing a template via my code would skip validation of $[], conditions and potential other things

Agreed, though for me the expansion of the template is the interesting part. The Pipeline Preview API could be used to validate the resulting YAML, if needed.

Regarding unit testing, the tests in main aren't compiling and I'm curious how I can help contribute to tests for the azure pipelines.

@ChristopherHX
Copy link
Owner

ChristopherHX commented Sep 30, 2023

I'm only doing integration testing, since more than a year.

For example add a line to your test pipeline here:

gharun --event azpipelines -C testworkflows/azpipelines/version-literal -W testworkflows/azpipelines/version-literal/pipeline.yml

and add your test files here: testworkflows/azpipelines/<yourtestname>/

@ChristopherHX
Copy link
Owner

ChristopherHX commented Sep 30, 2023

The Pipeline Preview API could be used to validate the resulting YAML, if needed.

Yes the pipeline preview api seem to only expand committed referenced templates. That's really a big limitation.

ChristopherHX added a commit that referenced this issue Oct 1, 2023
…221)

* Possible fix for #220

* add relative-and-absolute-paths test

---------

Co-authored-by: ChristopherHX <[email protected]>
@ChristopherHX
Copy link
Owner

I have added a test for this bug, thank you for improving this program.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants