Changing properties in Grails 3 application yml file through gradle - grails

There are some properties that I have in the default generated application.yml file in Grails 3. Take for example this property
test:
network:
path: '/home/cool/testing_data'
Now, the part that I want to do is change this property when I invoke the build script, so that it is different for the various OS that it might be executed on. I.e: On windows, that path should be 'E:/shared/testing_data', and on solaris, something different.
Using this post here, I can conclude that I can identify which OS I am currently on, so that I can potentially make some changes. Ex:
import org.apache.tools.ant.taskdefs.condition.Os
task checkWin() << {
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
// it is windows, lets change the path to not be linux like
}
}
So my question is, using gradle or any other means as necessary, can I change the properties in application.yml file to accommodate the different OS systems that the application might be deployed on? I am considering reading the application.yml file line by line and doing a string replacement, but I will resort to this only if there are no cleaner solutions.
Maybe am I using the wrong tool to solve this problem as is, so a good question to ask is, is there an easier way that I am missing here, possibly a similar approach to different "environments" like :test, dev, prod, for operating systems, already built into the core functionality of grails that I can re-use?

Just create application.groovy file in the same folder as application.yml is. In groovy file you can use any script to set value of properties.
For example add this line to application.groovy file (also remove option from yml):
test.network.path = Os.isFamily(Os.FAMILY_WINDOWS) ? 'd:\something' : '/home/something'

Related

Why do I get different runtimepaths depending on which API I use?

I'm trying to run Neovim 0.8.1. on a Windows 11 environment.
My setup is really minimal:
I downloaded nvim-win64.zip (of version 0.8.1) from Neovim's releases page on Github.
Extracted it and moved it to a folder at C:\test\nvim-win64
Started up Neovim by executing C:\test\nvim-win64\bin\nvim.exe
Not using any custom config.
When inspecting my runtimepath, there are 2 ways of doing this:
Using :set runtimepath? (the Vimscript way). This gives me:
runtimepath=~\AppData\Local\nvim,~\AppData\Local\nvim-data\site,C:\test\nvim-win64\share\nvim\runtime,C:\test\nvim-win64\share\nvim\runtime\pack\dist\opt\matchit,C:\test\nvim-win64\lib\nvim,~\AppData\Local\nvim-data\site\after,~\AppData\Local\nvim\after
Using :lua print(vim.inspect(vim.api.nvim_list_runtime_paths())) (the Lua way). this gives me:
{ "C:\\test\\nvim-win64\\share\\nvim\\runtime", "C:\\test\\nvim-win64\\share\\nvim\\runtime\\pack\\dist\\opt\\matchit", "C:\\test\\nvim-win64\\lib\\nvim" }
As you can see, it seems like using the Lua way I'm missing the local config directories in my runtimepath (the ~\AppData\Local\* paths).
Why am I seeing this difference? This is blocking me from using XDG_CONFIG_HOME to use my own config that I typically use, because it seems like it does not get included in the nvim_list_runtime_paths list, but it does appear in :set runtimepath?.
Nvim api function filters out non-existent directories. So there's a difference.
My issue was that my employer had decided to put ( and ) characters in my %USERPROFILE% environment variable, which ended up breaking a bunch of stuff (including the list I got from nvim_list_runtime_paths).
Putting those characters in %USERPROFILE% is a bad idea for many reasons, so I moved all of my files and folders out of any (sub)directory in %USERPROFILE% and right in C:\.
I also had to define XDG_CONFIG_HOME, XDG_DATA_HOME and XDG_STATE_HOME to point to a different location than the default location (which default within %USERPROFILE%).
This made all of my troubles go away!

With Jenkins Job Builder (JJB) what's the preferred way to inject values into a static set of job configuration files?

This bounty has ended. Answers to this question are eligible for a +100 reputation bounty. Bounty grace period ends in 14 hours.
frans is looking for an answer from a reputable source.
I have a working set of JJB YAML files successfully creating jobs and folders.
I now want to make certain values I use inside those YAML files configurable i.e. when running jenkins-jobs test|update -r jobfolder I want to set values for folder prefixes (to not damage existing production jobs), names for branches, nodes etc.
I don't want to use JJBs defaults approach for this since I'm already using it for configuration at a different place and it results in conflicts when used in projects and jobs together.
The ideal way of doing this I can think of would be a way to call JJB like this
jenkins-jobs test|update --define "folder-prefix=experimental/,node=test-node" -r jobfolder
Giving me variables I can use in the actual job definition files.
Since this option seemingly doesn't exist, I'm currently trying to provide files which contain those variables and somehow 'inject' them in my project.
Those are the approaches I can think of:
1 - having different configuration folders with YAML files inside, I would use like this:
jenkins-jobs test -r experimental-config:jobfolder
jenkins-jobs test -r production-config:jobfolder
with experimental-config and production-config being folders with additional files containing my configuration I can switch between.
But unfortunately I don't know how I would reference values I've defined in different yaml files. Is that even possible?
2 - having include files like described in the documentation
While that sounds promising I didn't manage to actually make this run. I tried to turn the following 'configuration header' I'm already using:
- dynamic-config: &dynamic-config
name: "dynamic-config"
folder-prefix: "experimental/"
node: "test-node"
[Rest of the file making use of dynamic-config]
into something making use of the !include statement like this:
!include: dynamic-config.yaml.inc
[Rest of the file making use of stuff defined in dynamic-config.yaml.inc]
giving me a seemingly unrelated parser error:
yaml.parser.ParserError: expected '<document start>', but found '<block sequence start>'
in "/home/me/my/project.yml", line 11, column 1
so I tried this snippet, which looks more like the example by putting it inside an existing element:
- dynamic-config: &dynamic-config
name: "dynamic-config"
!include: dynamic-config.yaml.inc
giving me a different error but still an error:
yaml.scanner.ScannerError: while scanning a simple key
in "/home/me/my/project.yml", line 7, column 5
could not find expected ':'
in "/home/me/my/project.yml", line 8, column 5
In both cases it doesn't make a difference whether or not the specified include file exists or not, which makes me doubt you can just 'include' a file like this at all.
What am I doing wrong here? Is there a more obvious / straight forward way to customize a jenkins-jobs run?
Update:
I somehow managed to use the !include tag for individual items now, like this:
- dynamic-config: &dynamic-config
name: "dynamic-config"
folder-prefix: !include: job-configs/active/folder-prefix.inc
branch-name: !include: job-configs/active/branch-name.inc
node-name: !include: job-configs/active/node-name.inc
But I wasn't able to put the whole dynamic-config element (with the anchor) into an include file yet.
2nd update:
Looks like I'm trying something similar as the guy from this question.
Can someone confirm, that this is currently still a problem? What's the JJB way of handling this?

Project level environment variable in source path

I'd like to specify an environment variable for use in the source path (library path) at a project level.
We often have a couple of versions checked out of our SVN repository at the same time in different directories, and I'd like to specify the repository root for a project in relative terms at a project level. I could then use that path in a project's source path and I wouldn't have to include indecipherable dot dot slashes (..\) in paths.
For example, say I have checked out trunk to c:\projects\trunk. Then underneath there I have a project in <repositoryroot>\Foo\Bar\ under trunk which uses the Delphi Spring framework under <repositoryroot>\components\external\Spring4d. I end up with a whole bunch of directories in the search path with ..\..\External\Spring4D\Source at the beginning. For example ..\..\External\Spring4D\Source\Base\Collections. I would like to be able to be able to use ${Spring4D} instead, producing ${Spring4D}\Base\Collections\, which is much less wordy and it means that if you move a project or component you can change one value and it updates all paths.
I know that you can do this on a Delphi level by specifying paths in Delphi's environment variables, but I would like to achieve the same thing on a project level or repository level.
Does anyone have any ideas on how to achieve this? Are there any settings or even add-ins that would allow this sort of functionality?
You can manually edit your project file (.dproj) and add a variable there:
<PropertyGroup>
<MyVariableName>MyVariableContent</MyVariableName>
</PropertyGroup>
Later on, you can refer to the content of that variable:
<DCC_UnitSearchPath>C:\Components;$(MyVariableName)</DCC_UnitSearchPath>
You can also define a new environment variable (SystemPropertiesAdvanced.exe -> Environment variables -> Add) and then refer to that variable using the same syntax, e.g.:
<DCC_UnitSearchPath>C:\Components;$(PATH)</DCC_UnitSearchPath>
(Note that it is a very bad idea to use PATH here, it's only an example of a variable which will exist in your environment.)
You could also employ some cmd script magic to to create environment variables that point to those subdirectories and at the end call the IDE, so these environment variables are available in the IDE in the same way as global environment variables would be (see pepak's answer for that).
Pointers:
%0 is the name of the current cmd file
use tilde for file name parts

How to create and load a configuration file in dxl

I have a script which saves some files at a given location. It works fine but when I send this code to someone else, he has to change the paths in the code. It's not comfortable for someone who does not know what is in that code and for me to explain every time where and how the code should be changed.
I want to get this path in a variable which will be taken from the configuration file. So it will be easier for everyone to change just this config file and nothing in my code. But I have never done this before and could not find any information on how I can do this in the internet.
PS: I do not have any code and I ask about an ultimate solution but it is really difficult to find something good in the internet about dxl, especially since I'm new with that. Maybe someone of you already does that or has an idea how it could be done?
DXL has a perm to read the complete context of a file into a variable: string readFile (string) (or Buffer readFile (string))
you can split the output by \n and then use regular expressions to find all lines that match the pattern
^\s*([^;#].*)\s*=\s*(.*)\s*$
(i.e. key = value - where comment lines start with ; or #)
But in DOORS I prefer using DOORS modules as configuration modules. Object Heading can be the key, Object Text can be the value.
Hardcode the full name of the configuration module into your DXL file and the user can modify the behaviour of the application.
The advantage over a file is that you need not make assumptions on where the config file is to be stored on the file system.
It really depends on your situation. You are going to need to be a little more specific about what you mean by "they need to change the paths in the code". What are these paths to? Are they DOORS module paths, are they paths to local/network files, or are the something else entirely?
Like user3329561 said, you COULD use a DOORS module as a configuration file. I wouldn't recommend it though, simply because that is not what DOORS modules were designed for. DOORS is fully capable of reading system files in one line at a time as well as all at once, but I can't recommend that option either until I know what types of paths you want to load and why.
I suspect that there is a better solution for your problem that will present itself once more information is provided.
I had the same problem, I needed to specify the path of my configuration file used in my dxl script.
I solved this issue passing the directory path as a parameter to DOORS.exe as follow:
"...\DOORS\9.3\bin\doors.exe" -dxl "string myVar = \"Hello Word\"
then in my dxl script, the variable myVar is a global variable.

Difference between App.Path and using a ShellObject.Self.Path

I am converting a VB6 application to VB.NET. In the code I am converting, it seems that the developer found the applications path two separate ways. However, it appears that he expects the two methods to produce different results.
Simple question:
What is the difference between calling these two lines of code:
strAppDataPath = CreateObject("Shell.Application").
NameSpace(ssfLOCALAPPDATA).Self.Path
and
strAppDataPath = App.Path
Explanation:
This is the code in question:
strAppDataPath = CreateObject("Shell.Application").
NameSpace(ssfLOCALAPPDATA).Self.Path
strAppDataPath = strAppDataPath & "\DataFolder\"
If (Not objFileSystem.FileExists(strAppDataPath & strAppDataFile)) Then
If (objFileSystem.FileExists(App.Path & strAppDataFile)) Then
...
End If
End If
The application's path is appended with \DataFolder\, and stored in the String strAppDatapath.
We check if the file strAppDataFile does not exist in strAppDatapath. Followed by checking if the file does exist in App.Path.
The concept behind what is going on makes sense to me: If the file doesn't exist in the subfolder, and if the file exists in App.Path, then do .... What I do not understand is why they didn't use one of the method for finding the application's path exclusively.
They don't point to the same path.
App.Path: Path where the currently executing EXE/DLL resides.
CreateObject("Shell.Application").NameSpace(ssfLOCALAPPDATA).Self.Path: Will point to the local (non-roaming) app data user folder. Same as the value in (user) environment variable LOCALAPPDATA.
Since Windows XP, the roaming & local app data paths are preferred places to store user settings and files (instead of the probably rights-restricted app folder).
So what the code does, is:
Look for strAppDataFile in %LOCALAPPDATA%\DataFolder\ (e.g. where "%LOCALAPPDATA%" could point to "C:\Users\UserName\AppData\Local\" on Windows Vista/7)
If not found, look for the same file in the application folder.
Please note that preferably applications should create an application specific sub-directory in local/roaming app data, e.g. use something like:
strAppDataPath = strAppDataPath & "\" & App.ProductName & "\DataFolder\"
' NOTE: Make sure to set the "Product Name" entry in the version information
' of the project settings
that could resolve to something like
"C:\Users\UserName\AppData\Local\My Application\DataFolder\"
My guess is that when the program is installed per-machine, a per-user location under LocalAppData is used. However during development or when installed per-user or as a portable application the application folder is used.
Some programmers use something like the code in question, while others make the decision by comparing App.Path against the ssfPROGRAMFILES path to determine the environment. The latter is probably preferable for a number of reasons but in the degenerate case where only one instance of the program exists on a machine they're equivalent.

Resources