oleg-shilo / cs-script

C# scripting platform
http://www.cs-script.net
MIT License
1.56k stars 234 forks source link

Using CS-Script inside a GitLab CI/CD Docker Runner #328

Closed UweKeim closed 1 year ago

UweKeim commented 1 year ago

Currently I'm trying to use a CS-Script with a Docker GitLab Runner running my CI/CD job inside a Docker image with latest .NET SDK.

I was able to successfully run a small script that basically prints out "Hello world".

What I'm failing currently is to use a real-world script with NuGet references.

Here are the last few lines of a failed GitLab Runner job:

...
$ dotnet $CSCS_EXE_FILEPATH ${CI_PROJECT_DIR}/Deploy/cicd-deploy.cs
NuGet> Processing NuGet packages...
  Determining projects to restore...
  Writing /tmp/tmpGI54V9.tmp
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/share/dotnet/sdk/7.0.202/trustedroots/codesignctl.pem'.
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/share/dotnet/sdk/7.0.202/trustedroots/timestampctl.pem'.
info : Adding PackageReference for package 'morelinq' into project '/tmp/csscript.core/.nuget/125/125.csproj'.
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/morelinq/index.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/morelinq/index.json 656ms
info : Restoring packages for /tmp/csscript.core/.nuget/125/125.csproj...
info :   GET https://api.nuget.org/v3-flatcontainer/morelinq/index.json
info :   OK https://api.nuget.org/v3-flatcontainer/morelinq/index.json 122ms
info :   GET https://api.nuget.org/v3-flatcontainer/morelinq/3.4.1/morelinq.3.4.1.nupkg
info :   OK https://api.nuget.org/v3-flatcontainer/morelinq/3.4.1/morelinq.3.4.1.nupkg 17ms
info : Installed morelinq 3.4.1 from https://api.nuget.org/v3/index.json with content hash onLx7+SB7B5/safFp0RgRDKCqBKawoM6/hqlcPUoxRImAOWpjxm4bGmXEU6plNWmZKIJ92mLEVPk1XuC4H+gRg==.
info : Package 'morelinq' is compatible with all the specified frameworks in project '/tmp/csscript.core/.nuget/125/125.csproj'.
info : PackageReference for package 'morelinq' version '3.4.1' added to file '/tmp/csscript.core/.nuget/125/125.csproj'.
info : Writing assets file to disk. Path: /tmp/csscript.core/.nuget/125/obj/project.assets.json
log  : Restored /tmp/csscript.core/.nuget/125/125.csproj (in [44](https://git.zeta-sw.com/zeta/zeta-time-tracker/-/jobs/1482#L44)5 ms).
Error: Specified file could not be compiled.
> -----
A new NuGet package has been installed. If some of its components are not found you may need to restart the script again.
> -----
Cannot process NuGet package 'morelinq'
Cleaning up project directory and file based variables
00:01
ERROR: Job failed: exit code 1

I'm not quite sure what's going on, but could imagine that those absolute paths starting at "/tmp/csscript.core/.nuget/..." are something that is not possible inside a runner.

Basically my repository is checked out by the runner into something like:

/builds/zeta/zeta-time-tracker

Where "build" is the root and the other folders are my GitLab group and GitLab repository name.

My questions

It seems that this issue over on the GitLab forum seems to be related and they tell not to use /tmp, if I understand them correctly.

Would be great if you could help me on making CS-Script run in a Docker CI/CD job ๐Ÿ˜Š.


Update 1

I've added some bash commands to my GitLab CI/CD script's job to write to "/tmp" and this seemed to work:

...
$ ls -l /tmp
total 12
drwx------ 2 root root [40](https://git.zeta-sw.com/zeta/zeta-time-tracker/-/jobs/1494#L40)96 Mar 14 14:22 8efe6eec-2b2c-4f53-b954-67d985928da6
drwx------ 2 root root 4096 Mar 14 14:22 91f4c9[42](https://git.zeta-sw.com/zeta/zeta-time-tracker/-/jobs/1494#L42)-724b-4405-8c8d-93554b72d0f4
drwx------ 2 root root 4096 Mar 14 14:22 MSBuildTemproot
$ mkdir /tmp/uwekeim
$ touch /tmp/uwekeim/info.txt
$ ls -l /tmp/uwekeim
total 0
-rw-r--r-- 1 root root 0 Mar 22 21:13 info.txt

So creating a directory and a file seems to work in general, maybe my above assumption was a red herring.

This leaves me totally clueless for now what might be the cause of CS-Script failing to handle the NuGet packages.

Update 2

This is a minimal CS-Script script that runs successfully locally on my Windows machine with the Windows version of CS-Script and also runs successfully inside my Docker CI/CD image with the Linux version of CS-Script:

using System;

public static class Processor
{
    public static int Main()
    {
        Console.WriteLine("Hello from cicd-test-01.cs");
        return 0;
    }
}

This is a minimal CS-Script script that runs successfully locally on my Windows machine with the Windows version of CS-Script and fails to run inside my Docker CI/CD image with the Linux version of CS-Script:

//css_nuget -force:3600 Newtonsoft.Json

using System;
using Newtonsoft.Json;

public static class Processor
{
    public static int Main()
    {
        Console.WriteLine("Hello from cicd-test-02.cs");

        var json = JsonConvert.SerializeObject(new { success = true } );
        Console.WriteLine(json);

        return 0;
    }
}

The error that is printed from the runner is:

$ dotnet $CSCS_EXE_FILEPATH ${CI_PROJECT_DIR}/Etc/Testing/cicd-test-02.cs
NuGet> Processing NuGet packages...
  Determining projects to restore...
  Writing /tmp/tmprkAC1L.tmp
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/share/dotnet/sdk/7.0.202/trustedroots/codesignctl.pem'.
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/share/dotnet/sdk/7.0.202/trustedroots/timestampctl.pem'.
info : Adding PackageReference for package 'Newtonsoft.Json' into project '/tmp/csscript.core/.nuget/67/67.csproj'.
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json 121ms
info : Restoring packages for /tmp/csscript.core/.nuget/67/67.csproj...
info :   GET https://api.nuget.org/v3-flatcontainer/newtonsoft.json/index.json
info :   OK https://api.nuget.org/v3-flatcontainer/newtonsoft.json/index.json 120ms
info :   GET https://api.nuget.org/v3-flatcontainer/newtonsoft.json/13.0.3/newtonsoft.json.13.0.3.nupkg
info :   OK https://api.nuget.org/v3-flatcontainer/newtonsoft.json/13.0.3/newtonsoft.json.13.0.3.nupkg 14ms
info : Installed Newtonsoft.Json 13.0.3 from https://api.nuget.org/v3/index.json with content hash HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==.
info : Package 'Newtonsoft.Json' is compatible with all the specified frameworks in project '/tmp/csscript.core/.nuget/67/67.csproj'.
info : PackageReference for package 'Newtonsoft.Json' version '13.0.3' added to file '/tmp/csscript.core/.nuget/67/67.csproj'.
info : Writing assets file to disk. Path: /tmp/csscript.core/.nuget/67/obj/project.assets.json
log  : Restored /tmp/csscript.core/.nuget/67/67.csproj (in 552 ms).
Error: Specified file could not be compiled.
> -----
A new NuGet package has been installed. If some of its components are not found you may need to restart the script again.
> -----
Cannot process NuGet package 'Newtonsoft.Json'

Just for completeness here is my ".gitlab-ci.yml" file with the definitions:

image: mcr.microsoft.com/dotnet/sdk:latest

default:
  tags:
    - ubuntu 

stages:
  - tests-01

variables:
  CSCS_EXE_FILEPATH: '${CI_PROJECT_DIR}/DevelopmentTools/cs-script-linux/cscs.dll'

tests-01:
  stage: tests-01
  script:
    - dotnet $CSCS_EXE_FILEPATH --version
    - dotnet $CSCS_EXE_FILEPATH ${CI_PROJECT_DIR}/Etc/Testing/cicd-test-01.cs
    - dotnet $CSCS_EXE_FILEPATH ${CI_PROJECT_DIR}/Etc/Testing/cicd-test-02.cs
    - dotnet $CSCS_EXE_FILEPATH ${CI_PROJECT_DIR}/Etc/Testing/cicd-test-03.cs
oleg-shilo commented 1 year ago

Uwe, I suspect that it is that the current CS-Script package probing algorithm is failing. Can you check if that test script from #326 identifies the package assembly correctly?

If it does then I can prioritize its integration with the codebase.

Note, that you may need to update the packages repo path:

var nugetRepo =
    Environment.OSVersion.Platform == PlatformID.Win32NT ?
        Environment.ExpandEnvironmentVariables(@"%userprofile%\.nuget\packages") :
        "~/.nuget/packages";
UweKeim commented 1 year ago

Thank you, Oleg!

I've run the script in a new CI/CD job with this result:

...
$ dotnet $CSCS_EXE_FILEPATH ${CI_PROJECT_DIR}/Etc/Testing/testscript-for-oleg.cs
/root/.local/share/Temp/csscript.core/nuget/349af62d-da05-42cb-a458-d910843[20](https://git.zeta-sw.com/zeta/zeta-shared-ci-assets/-/jobs/1513#L20)791/nuget.ref.csproj
Restoring packages...
    00:00:03.0717686
Mapping packages to assemblies...
================
Could not find a part of the path '/builds/zeta/zeta-shared-ci-assets/Etc/Testing/~/.nuget/packages'.
System.IO.DirectoryNotFoundException: Could not find a part of the path '/builds/zeta/zeta-shared-ci-assets/Etc/Testing/~/.nuget/packages'.
   at System.IO.Enumeration.FileSystemEnumerator`1.CreateDirectoryHandle(String path, Boolean ignoreNotFound)
   at System.IO.Enumeration.FileSystemEnumerator`1.Init()
   at System.IO.Enumeration.FileSystemEnumerable`1..ctor(String directory, FindTransform transform, EnumerationOptions options, Boolean isNormalized)
   at System.IO.Enumeration.FileSystemEnumerableFactory.UserDirectories(String directory, String expression, EnumerationOptions options)
   at System.IO.Directory.InternalEnumeratePaths(String path, String searchPattern, SearchTarget searchTarget, EnumerationOptions options)
   at System.IO.Directory.GetDirectories(String path, String searchPattern, EnumerationOptions enumerationOptions)
   at Program.<Main>$(String[] args)
Unhandled exception. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.IO.DirectoryNotFoundException: Could not find a part of the path '/builds/zeta/zeta-shared-ci-assets/Etc/Testing/~/.nuget/packages'.
   at System.IO.Enumeration.FileSystemEnumerator`1.CreateDirectoryHandle(String path, Boolean ignoreNotFound)
   at System.IO.Enumeration.FileSystemEnumerator`1.Init()
   at System.IO.Enumeration.FileSystemEnumerable`1..ctor(String directory, FindTransform transform, EnumerationOptions options, Boolean isNormalized)
   at System.IO.Enumeration.FileSystemEnumerableFactory.UserDirectories(String directory, String expression, EnumerationOptions options)
   at System.IO.Directory.InternalEnumeratePaths(String path, String searchPattern, SearchTarget searchTarget, EnumerationOptions options)
   at System.IO.Directory.GetDirectories(String path, String searchPattern, EnumerationOptions enumerationOptions)
   at Program.<Main>$(String[] args)
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
   --- End of inner exception stack trace ---
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at csscript.LocalExecutor.InvokeStaticMain(Assembly compiledAssembly, String[] scriptArgs)
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__1[28](https://git.zeta-sw.com/zeta/zeta-shared-ci-assets/-/jobs/1513#L28)_1(Object state)
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
/bin/bash: line 1[40](https://git.zeta-sw.com/zeta/zeta-shared-ci-assets/-/jobs/1513#L40):    12 Aborted                 (core dumped) dotnet $CSCS_EXE_FILEPATH ${CI_PROJECT_DIR}/Etc/Testing/testscript-for-oleg.cs

Update 1

I've changed the var nugetRepo = ... part to this:

var nugetRepo =
    Environment.OSVersion.Platform == PlatformID.Win32NT ?
        Environment.ExpandEnvironmentVariables(@"%userprofile%\.nuget\packages") :
        "/tmp/.nuget/packages";
Directory.CreateDirectory(nugetRepo); // Added this one, too!

Then it ran without errors:

$ dotnet $CSCS_EXE_FILEPATH ${CI_PROJECT_DIR}/Etc/Testing/testscript-for-oleg.cs
/root/.local/share/Temp/csscript.core/nuget/17494f34-6482-4e4c-9d70-926e1a842d26/nuget.ref.csproj
Restoring packages...
    00:00:03.0874076
Mapping packages to assemblies...
================

================
    00:00:00.0064136

But still did not find the MoreLinq repo, even with the brute force directory checking with "*".

Update 2

OK, I completely misunderstood the meaning of nugetRepo. After reading this Stack Overflow answer I did this:

var nugetRepo =
    Environment.OSVersion.Platform == PlatformID.Win32NT ?
        Environment.ExpandEnvironmentVariables(@"%userprofile%\.nuget\packages") :
        Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "/.nuget/packages";

This seems to be the right thing as it now prints:

$ dotnet $CSCS_EXE_FILEPATH ${CI_PROJECT_DIR}/Etc/Testing/testscript-for-oleg.cs
/root/.local/share/Temp/csscript.core/nuget/f63013c5-bb50-4434-916a-b9f5e89b232f/nuget.ref.csproj
Restoring packages...
    00:00:03.5686736
Mapping packages to assemblies...
================
    /root/.nuget/packages/morelinq/3.4.1/lib/net6.0/MoreLinq.dll 
================
    00:00:00.0097046

To further simplify the nugetRepo variable, a platform agnostic way could be to write it as something like that:

var nugetRepo = 
    Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages");
oleg-shilo commented 1 year ago

That is a perfect result. Great. Will try to come up with a working solution over the weekend

oleg-shilo commented 1 year ago

But I would still allow custom location just in case:

var nugetRepo = 
    Environment.GetEnvironmentVariable("CSS_CUSTOM_NUGET_REPO") ??
    Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages");
UweKeim commented 1 year ago

This could come up super helpful! Great idea! โ™ฅ๏ธ

UweKeim commented 1 year ago

Don't know whether this is relevant here; the documentation says that you can define a custom nuget.config file in the root of a project repository with an optional globalPackagesFolder entry. To quote:

The location of the default global packages folder. The default is %userprofile%\.nuget\packages (Windows) or ~/.nuget/packages (Mac/Linux). A relative path can be used in project-specific nuget.config files. This setting is overridden by the NUGET_PACKAGES environment variable, which takes precedence.

I don't need this feature, I just wanted to document it here, in case someone is looking it up some time in the future ๐Ÿ™‚.


Update 1

Or maybe the NUGET_PACKAGES environment variable could be queried, too? Like e.g.:

var nugetRepo = 
    Environment.GetEnvironmentVariable("CSS_CUSTOM_NUGET_REPO") ??
    Environment.GetEnvironmentVariable("NUGET_PACKAGES") ??
    Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages");

Just an idea.

oleg-shilo commented 1 year ago

Done. Have a look at https://github.com/oleg-shilo/cs-script/releases/tag/v4.6.5.2-rc2

UweKeim commented 1 year ago

Thank you very much, Oleg!

I've tried this script ("cicd-test-02.cs") again:

//css_nuget -force:3600 Newtonsoft.Json

using System;
using Newtonsoft.Json;

public static class Processor
{
    public static int Main()
    {
        Console.WriteLine("Hello from cicd-test-02.cs");

        var json = JsonConvert.SerializeObject(new { success = true } );
        Console.WriteLine(json);

        return 0;
    }
}

Running with v4.6.5.2-rc2 on my Windows 11 machine succeeds and prints this:

Hello from cicd-test-02.cs
{"success":true}

Running with v4.6.5.2-rc2 inside an Ubuntu GitLab Runner fails with these messages:

$ dotnet /builds/zeta/zeta-shared-ci-assets/DevelopmentTools/cs-script-linux/cscs.dll /builds/zeta/zeta-shared-ci-assets/Etc/Testing/cicd-test-02.cs
NuGet> Processing NuGet packages...
  Determining projects to restore...
  Writing /tmp/tmpXPmxnr.tmp
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/share/dotnet/sdk/7.0.202/trustedroots/codesignctl.pem'.
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/share/dotnet/sdk/7.0.202/trustedroots/timestampctl.pem'.
info : Adding PackageReference for package 'Newtonsoft.Json' into project '/tmp/csscript.core/.nuget/23/23.csproj'.
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json 119ms
info : Restoring packages for /tmp/csscript.core/.nuget/23/23.csproj...
info :   GET https://api.nuget.org/v3-flatcontainer/newtonsoft.json/index.json
info :   OK https://api.nuget.org/v3-flatcontainer/newtonsoft.json/index.json 121ms
info :   GET https://api.nuget.org/v3-flatcontainer/newtonsoft.json/13.0.3/newtonsoft.json.13.0.3.nupkg
info :   OK https://api.nuget.org/v3-flatcontainer/newtonsoft.json/13.0.3/newtonsoft.json.13.0.3.nupkg 14ms
info : Installed Newtonsoft.Json 13.0.3 from https://api.nuget.org/v3/index.json with content hash HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==.
info : Package 'Newtonsoft.Json' is compatible with all the specified frameworks in project '/tmp/csscript.core/.nuget/23/23.csproj'.
info : PackageReference for package 'Newtonsoft.Json' version '13.0.3' added to file '/tmp/csscript.core/.nuget/23/23.csproj'.
info : Writing assets file to disk. Path: /tmp/csscript.core/.nuget/23/obj/project.assets.json
log  : Restored /tmp/csscript.core/.nuget/23/23.csproj (in 4[33](https://git.zeta-sw.com/zeta/zeta-shared-ci-assets/-/jobs/1542#L33) ms).
Error: Specified file could not be compiled.
> -----
A new NuGet package has been installed. If some of its components are not found you may need to restart the script again.
> -----
Cannot process NuGet package 'Newtonsoft.Json'

Basically, from the above excerpt, my command line is:

dotnet /builds/zeta/zeta-shared-ci-assets/DevelopmentTools/cs-script-linux/cscs.dll /builds/zeta/zeta-shared-ci-assets/Etc/Testing/cicd-test-02.cs

Maybe I'm calling CS-Script wrong?

Is there anything other way I can assist on debugging/resolving this?

I could as well set up a Ubuntu Server VM and test my scripts inside this one, too. So no testing in a Docker container but a full Ubuntu, in case this would help?


Update 1

I've tried to add the -dbg switch to the CS-Script call:

$ dotnet $CSCS_EXE_FILEPATH -dbg ${CI_PROJECT_DIR}/Etc/Testing/cicd-test-02.cs
NuGet> Processing NuGet packages...
  Determining projects to restore...
  Writing /tmp/tmpityRfC.tmp
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/share/dotnet/sdk/7.0.202/trustedroots/codesignctl.pem'.
info : X.509 certificate chain validation will use the fallback certificate bundle at '/usr/share/dotnet/sdk/7.0.202/trustedroots/timestampctl.pem'.
info : Adding PackageReference for package 'Newtonsoft.Json' into project '/tmp/csscript.core/.nuget/12/12.csproj'.
info :   GET https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json
info :   OK https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json 126ms
info : Restoring packages for /tmp/csscript.core/.nuget/12/12.csproj...
info :   GET https://api.nuget.org/v3-flatcontainer/newtonsoft.json/index.json
info :   OK https://api.nuget.org/v3-flatcontainer/newtonsoft.json/index.json 437ms
info :   GET https://api.nuget.org/v3-flatcontainer/newtonsoft.json/13.0.3/newtonsoft.json.13.0.3.nupkg
info :   OK https://api.nuget.org/v3-flatcontainer/newtonsoft.json/13.0.3/newtonsoft.json.13.0.3.nupkg [24](https://git.zeta-sw.com/zeta/zeta-shared-ci-assets/-/jobs/1546#L24)ms
info : Installed Newtonsoft.Json 13.0.3 from https://api.nuget.org/v3/index.json with content hash HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==.
info : Package 'Newtonsoft.Json' is compatible with all the specified frameworks in project '/tmp/csscript.core/.nuget/12/12.csproj'.
info : PackageReference for package 'Newtonsoft.Json' version '13.0.3' added to file '/tmp/csscript.core/.nuget/12/12.csproj'.
info : Writing assets file to disk. Path: /tmp/csscript.core/.nuget/12/obj/project.assets.json
log  : Restored /tmp/csscript.core/.nuget/12/12.csproj (in 906 ms).
Error: Specified file could not be compiled.
> -----
A new NuGet package has been installed. If some of its components are not found you may need to restart the script again.
> -----
Cannot process NuGet package 'Newtonsoft.Json'

Don't know whether this help, as it doesn't seem to add more output.

oleg-shilo commented 1 year ago

The message Processing NuGet packages.... is only printed with the legacy NuGet support. Meaning that the new algorithm is not enabled in your environment.

Is it possible that you forgot to enable the new nuget algorithm?

css -config:set:LegacyNugetSupport=false

By default it is disabled.

BTW -force:3600 will be ignored in the new approach. Please read about it here: https://github.com/oleg-shilo/cs-script/wiki/NuGet-Support

UweKeim commented 1 year ago

OMG, shame on me! I did not even understand that I have to call this.

I've successfully tried to manage this on Windows, since there is a "css.exe".

For Linux, I've done it this way (since the css alias doesn't seem to work):

$ dotnet $CSCS_EXE_FILEPATH -config:set:LegacyNugetSupport=false
set: LegacyNugetSupport: False
$ dotnet $CSCS_EXE_FILEPATH -dbg ${CI_PROJECT_DIR}/Etc/Testing/cicd-test-02.cs
Restoring packages...
Mapping packages to assemblies1111...
Hello from cicd-test-02.cs
{"success":true}

(I.e. calling cscs.dll instead of css).

And this also worked! Awesome ๐ŸŽ‰๐Ÿ˜Š

You've made my sunday!

oleg-shilo commented 1 year ago

Yey!!! Will prepare the official release asap

oleg-shilo commented 1 year ago

I will also publish it as a .NET tool.

Meaning that you will be able to use it with css alias (https://github.com/oleg-shilo/cs-script/issues/317#issuecomment-1484062299)

I tested it already on Win but expect Linux to do the same.

UweKeim commented 1 year ago

Thank you!

So instead of manually downloading the 7z files with CS-Script for Linux and Windows, I simply can do on both platforms a

dotnet tool install --global cs-script.cli

And always have the latest version?

That would be hell of an improvement over my current workflow.

oleg-shilo commented 1 year ago

Yep. Choc does the same but it is not available on Linux. On Linux, you have to use

In Ubuntu terminal:

repo=https://github.com/oleg-shilo/cs-script/releases/download/v4.6.5.0/; file=cs-script_4.6-5.deb; rm $file; wget $repo$file; sudo dpkg -i $file

Depending on the user context you may need to add permissions to the CS-Script temp dir sudo chmod -R 777 /tmp

Obviously having the same distribution channel (dotnet) on all OSs is a preferred approach.

The only thing that you need to do manually is to stop any running instance of the script engine: css -servers:stop Cocho can do it automatically but dotnet cannot :(

oleg-shilo commented 1 year ago

yes the "get latest version" command will be something like that:

css -servers:stop
dotnet tool update --global cs-script.cli
UweKeim commented 1 year ago

Since my CI/CD jobs fire up a new Docker image upon every run, I guess I do not have to do the stopping at all.

Will be happy to test as soon as it is released โ™ฅ๏ธ.

Thanks a million times for all your help!

Not only is the CS-Script engine superior to all the other .NET scripting engines out there in terms of features, but what makes it outstanding is your awesome, dedicated support!

oleg-shilo commented 1 year ago

Not a prob :o)

oleg-shilo commented 1 year ago

Done. Release v4.7.0

You can install it as a the tool now: https://www.nuget.org/packages/cs-script.cli

UweKeim commented 1 year ago

Thank you very much, Oleg.

On Windows, I can now run my scripts successfully via:

css my-script.css

In my GitLab runner, after executing these scripts successfully:

dotnet tool install --global cs-script.cli
dotnet tool update --global cs-script.cli

I tried different ways to call CS-Script, all of them failed with "command not found" or similar errors:

Do you have any idea on how I could call it successfully inside my Ubuntu GitLab Runner?


Update 1

I've fired up an Ubuntu 22 Server (Ubuntu 22.04.2 LTS), installed .NET SDK 7 and then installed CS-Script via dotnet tool update --global cs-script.cli:

root@server:/home/ukeim# dotnet tool update --global cs-script.cli

Welcome to .NET 7.0!
---------------------
SDK Version: 7.0.202

Telemetry
---------
The .NET tools collect usage data in order to help us improve your experience. It is collected by Microsoft and shared with the community. You can opt-out of telemetry by setting the DOTNET_CLI_TELEMETRY_OPTOUT environment variable to '1' or 'true' using your favorite shell.

Read more about .NET CLI Tools telemetry: https://aka.ms/dotnet-cli-telemetry

----------------
Installed an ASP.NET Core HTTPS development certificate.
To trust the certificate run 'dotnet dev-certs https --trust' (Windows and macOS only).
Learn about HTTPS: https://aka.ms/dotnet-https
----------------
Write your first app: https://aka.ms/dotnet-hello-world
Find out what's new: https://aka.ms/dotnet-whats-new
Explore documentation: https://aka.ms/dotnet-docs
Report issues and find source on GitHub: https://github.com/dotnet/core
Use 'dotnet --help' to see available commands or visit: https://aka.ms/dotnet-cli
--------------------------------------------------------------------------------------
You can invoke the tool using the following command: css
Tool 'cs-script.cli' (version '4.7.0') was successfully installed.

Next, I tried a simple css call:

root@server:/home/ukeim# css
Command 'css' not found, but there are 16 similar ones.

I've also tried all other variations of the command like dotnet css, cscs, cscs.exe, css.exe, css.dll etc. without any success.

So it seems that this is not just an issue inside a CI/CD Ubuntu Docker GitLab Runner but also on a full Ubuntu system.

Update 2

I was able to locate css at ~/.dotnet/tools/css.

So with this information I was able to run it this way:

root@server:~/.dotnet/tools# ~/.dotnet/tools/css
C# Script execution engine (.NET Core). Version 4.7.0.0.
Copyright (C) 2004-2020 Oleg Shilo. www.csscript.net (github.com/oleg-shilo/cs-script)

   CLR:             7.0.4
   System:          Unix 5.15.0.67
   Architecture:    x64
   Script engine:   /root/.dotnet/tools/.store/cs-script.cli/4.7.0/cs-script.cli/4.7.0/tools/net7.0/any/cscs.dll
   Compiler engine: csc (/usr/share/dotnet/sdk/7.0.202/Roslyn/bincore/csc.dll)
                    -> dotnet (/usr/share/dotnet/dotnet)
   NuGet manager:   dotnet
   NuGet cache:     <not found>
   Custom commands: /usr/share/cs-script/commands
   Global includes: /usr/share/cs-script/inc

Not sure whether it is intended to run it with the absolute path only, but at least it seems to run now ๐Ÿ˜Š๐ŸŽ‰

I'll try something similar now in my CI/CD script.

Update 3

Yes, my CI/CD job now runs successfully:

image: mcr.microsoft.com/dotnet/sdk:latest

default:
  tags:
    - ubuntu 

stages:
  - tests-01

tests-01:
  stage: tests-01
  script:
    - dotnet tool install --global cs-script.cli
    - dotnet tool update --global cs-script.cli
    - ~/.dotnet/tools/css -config:set:LegacyNugetSupport=false
    - ~/.dotnet/tools/css ${CI_PROJECT_DIR}/Etc/Testing/cicd-test-01.cs
    - ~/.dotnet/tools/css ${CI_PROJECT_DIR}/Etc/Testing/cicd-test-02.cs
    - ~/.dotnet/tools/css ${CI_PROJECT_DIR}/Etc/Testing/cicd-test-03.cs

All three tests scripts "cicd-test-01.cs", "cicd-test-02.cs", "cicd-test-03.cs" run without errors.

oleg-shilo commented 1 year ago

Thank you Uwe,

I am still discovering ".NET Tool" insights and at the moment I was only able to check how it works on Windows.

Linux is yet to come and my assumption is that it offers the identical functionality as Win. Judging from your report it is not the case. On Win I was able to call css right after the installation.

It does look like an oversight from the SDK team. Though there is an interesting defect opened from 2018. Exactly about that: https://github.com/dotnet/dotnet-docker/issues/520

As for your situation, you probably can fix it by adding /root/.dotnet/tools/ to system PATH.

Or you can create an alias alias css='/root/.dotnet/tools/css'. Now you can just call css and it will run it from the right path.

If you want to make this change permanent you can do this:

echo "alias css=' /root/.dotnet/tools/csc'" >> ~/.bashrc
source ~/.bashrc

Alternatively, you can add

RUN echo "PATH=/m:ybin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.dotnet/tools
" > /etc/environment

to your dockerfile See https://stackoverflow.com/questions/67849660/how-to-set-system-wide-path-in-ubuntu20-04-docker-image discussion

oleg-shilo commented 1 year ago

The whole idea of ".NET Tool" is more attractive for vendors because:

But it comes with a price. You cannot have any behaviour executed either before or after installation.

With Choco, you can, and with Choco deployment, CS-Script tool package sets the PATH after installation. But for dotnet-tool on Linux it needs to be done manually.

UweKeim commented 1 year ago

Thanks, Oleg โ™ฅ๏ธ

Using ~/.dotnet/tools/css seems to be totally working and is absolutely sufficient for my use cases.