With Buildbot Source Step: why can 'codebase' not be set via Interpolate while 'repourl' can? - buildbot

I have a factory that I use in several builders and I set builder specific settings via util.Property and util.Interpolate. While this works fine for repourl and branch it simply doesn't work for codebase. The following piece of code shows the source step how I would like to use it in my Buildbot configuration.
factory.addStep(
steps.Git(repourl=util.Interpolate('git://repo_base_path/%(prop:build_repository)s', default=''),
branch=util.Property('build_branch', default='master'),
mode='full',
codebase=util.Interpolate('%(prop:build_repository)s', default=''),
method='copy', submodules=True, clobberOnFailure=True)
)
)
Without the codebase part all worked fine. I then figured I would need to set the codebase for some cases so I added the codebase line, resulting in the following error:
[-] Configuration Errors:
[-] error while parsing config file: sequence item 1: expected
string, Interpolate found traceback in logfile
Does anybody know why it is not possible to set the codebase via Interpolate while it is no problem to do the same thing with repourl?
Does somebody have an idea how to set the codebase for the source step to something different from '' and still not create a separate factory instance for every builder?
Any insights into this and any helpful suggestion is highly appreciated.

I think this is a bug in Buildbot. Looking at the Buildbot 0.8.12 sources, I can see that in buildbot/steps/source/git.py, in class Git, the renderables attribute includes "codebase", which should mean that you can use Interpolate in this way. Presumably some other code is assuming it can interpret codebase as a string at the time the configuration is parsed.
In other words, as far as I can tell, you're doing something that the Git class claims to support.
It looks like the old-style Git support in buildbot/steps/source/oldsource.py doesn't support codebase being a renderable, but it doesn't look to me like you're using that. I'm not entire sure, though, because I'm not sure what steps.Git refers to.

Related

Missing type for additionalProperties in generated scala-play-server code

I was playing around with openapi-generator, and cant find a way to get it to generate valid scala code for scala-play-server.
I use the petstore.json I downloaded from swagger.io, and run
openapi-generator generate -i petstore.json -g scala-play-server
It seems to kinda work, except, the models it generates look like this:
case class Tag(
id: Option[Long],
name: Option[String]
additionalProperties:
)
... which, of course, isn't valid scala code, and fails to compile.
I tried adding
--additional-properties=disallowAdditionalPropertiesIfNotPresent=false
to command line as some website I googled suggested, but that didn't make any difference (and neither did changing false to true).
I guess, I could just put together a sed script, to run on all generated files and replace additionalProperties: with additionalProperties: Map[String, Any] (or just remove those lines completely - no idea why I would want them there), but thought I'd just ask first in case someone knows about an easy fix that wouldn't be this "hacky" ...
Disclaimer, I am not a scala developer, but I spend a lot of time with the open-api-generator.
It appears this is a known bug that was reported in September 2022. However, it doesn't seem to have any comments or traction. Feel free to add comments to the existing ticket. Sometimes that helps them gain visibility.
I don't know if it matters, but I tested the other scala server generators, and all of them generate the class without the additional properties. So, if you are able to use a different scala server generator, that may be a work around.
Another potential work around, if you don't ever plan to use the additionalProperties feature of OAS, would be to remove it from the mustache template. You can do this via templating. Copy the caseClass.mustache and the model.mustache templates into a directory of your choosing, and delete the references to the additionalProperties. Then, add the template directory to your CLI generator via -t/--template.
I tried using the templating method myself and it works, however you will no longer be able to use the additionalProperties feature from OAS in your schema.

Read YAML config through Rest API

I have a really complicated system which use multiple languages and frameworks (Java Python Scala Bash). In each module I need to retrieve configuration values which are similar and change frequently. Currently I'm maintaining multiple conf files which holds lots of duplicates.
I wonder if there is out of the box RestAPI which can retrieve variables by demand from remote location.
All I manage to find by now are ways to load the entire file from remote source which is half a solution from me:
YAML.parse(open('https://link_to_file/file.yaml'))
My goal, which I fail to find a lead to it, is to make a direct call.
MyRemoteAPI.get("level1.level2.x")
P.S
YAML is not mandatory solution for me, I'm Open for suggestions.
I don't know about an out-of-the-box API, but it's fairly trivial to build. Make a service that will read the YAML file and traverse to the appropriate key. e.g. using a dynamic language like Ruby (+Rails), you could do something like
def value
config = YAML.load_file '/local/path/to/config.yaml'
render plain: config.dig(params[:key].split('.'))
end
dig essentially traverses a structure and safely returns nil if a key isn't found, so this returns the value at the "leaf" of the requested path.
You might also want to cache the structure in memory to prevent constantly reading from the file, e.g. could do something like ##config ||= YAML.parse(open('https://link_to_file/file.yaml')) or config = Rails.cache.fetch('config', expire_in: 1.hour) { ... }. And/or cache the API's HTTP response.

How does Server.call work in elixir-mongo?

I'm learning Elixir and attempting to use the elixir-mongo library. During the auth/1 command, A the function uses Server.call, piping in the MongoDB request string. looking at the Mongo.Server class, it does not appear to be an actual genserver, nor have a method to match call/1. How is this working?
With high probability it doesn't work. Mongo.Server module doesn't export call function. There are no macros that generate it magically. My guess is that master branch is currently broken. If you are using the library and want to dig into the sources make sure you are looking at the same tag as the version you are using in your project.
Also, there are no classes and methods in Elixir. There are modules and functions :)

How to replace a shared file when deploying code with Capistrano?

Update: TL;DR there seems to be no built-in way to achieve this, so a custom task is an easy solution.
Capistrano provides facilities to share files and directories over all releases. This is convenient and provides even some safety on files that should not be easily changed (or must remain the same across releases), e.g. a database configuration file.
But when it comes to replace or just update one of these shared files, I end up doing it manually, directly on the target machine. I would like to improve on that, for instance by asking Capistrano to overwrite some or all shared files when deploying. A kind of --force flag with some granularity.
I am not aware of any such kind of facility, and failing so far in my search. Any pointer?
Thinking about it
One of the reason why this facility does not exist (except that I did not find it!) is that it may be harder than it looks. For example, let's assume we have a shared database configuration file, and we exclude it from version control for security reason (common practice). Current release relies on version 1 of the DB configuration. The next release requires version 2 of the DB configuration. If the deployment goes well, everything's good. It gets harder when rolling back after some error with the new release (e.g. a regression), as version 1 must then be available.
Such automation would be cool and convenient, but dangerous as well. Yet I have practical use cases at hand.
I created a template method to do this. For example, I could have a task like this:
task :create_database_yml do
on roles(:app, :db) do
within(shared_path) do
template "local/path/to/database.yml.erb",
"config/database.yml",
:mode => "600"
end
end
end
And then I have a database.yml.erb template that uses things like fetch(:database_password) to fill in appropriate values. You can use the ask method in Capistrano to prompt for these values so they are never committed.
The implementation of template can be very simple: you just need to read the file, pass it through ERB, and then use Capistrano's upload! to place the results on the server.
My version is a little more complicated than yours probably needs to be, but in case you are curious:
https://github.com/mattbrictson/capistrano-mb/blob/7600440ecd3331945d03e059368b75849857f1fb/lib/capistrano/mb/dsl.rb#L104
One approach is to use a system configuration tool like Chef or Puppet to deploy the configuration files distinctly from Capistrano.
Another approach is to create a custom task to do this: https://coderwall.com/p/wgs6gw/copy-local-files-to-remote-server-using-capistrano-3
I personally don't change on-server configs often enough or on enough servers yet to have tried to automate it. Crafting an scp command which copies the desired config file to all of the required servers has sufficed in the past.

Getting job repository URL in Jenkins build plugin

I am writing a build notification plugin for Jenkins. The SCM repository URL (SCM being git to begin with) contains useful information I'd want to get to in my code. Being the beginner with the Jenkins API that I am, I am having trouble figuring out how I should go about retrieving the job's repository location. Is this doable, and if so, how?
The repository is available in the config.xml of the job.
http://[jenkins server]/job/[job]/config.xml
Finally found the answer! The method needed is not defined in the abstract SCM class, but by the classes which extend it. So when you call project.getSCM() you have to then cast it to the type of SCM that you actually have (GitSCM, SubversionSCM, etc.).
I am developing my plugin to work with Subversion, so I looked through the source code for the Subversion Plugin, and found the method getLocations which returns a ModuleLocation[] which contains information on all the SVN repositories in that project. Simply looping through the ModuleLocation[] and calling getSVNURL() gets me the information I want. I can then play around with the SVNURL as needed (toString() gives me the full repository path).
In your case, for Git, the source code shows that there is a method called getRepositories(), which returns a List<RemoteConfig>. Look through the RemoteConfig source code to see which method gets you the information you need. (I believe getURIs() will do the trick).
I managed to get URL of SVN repository for a particular job using following code:
String jobName = manager.build.project.getName()
def job = hudson.model.Hudson.instance.getItem(jobName)
def svnScm = job.scm
def svnLocation = svnScm.getLocations()
def svnURLstr = svnLocation[0].getSVNURL().toString()
Perhaps it will be useful to someone.