How do I access files in a Shared Library? - jenkins

I have a Shared Library with a .groovy script that I call in a jenkinsfile like this:
MySharedLibFunction{ .. some args}
I also have a .ps1 file in my shared library I want to execute. But if I do powershell pwd from in my shared library function when I call that function from my jenkinsfile the current working directory is the jenkins working directory of my pipeline where the jenkinsfile is located (which is usually what you want).
Is there a way to access files in the shared lib? I want to do powershell -File ps1FileInMySharedLibVarsFolder.ps1

You can only get the contents using the built-in step libraryResource. That's why have the following functions in my shared library to copy it to a temporary directory and return the path to the file:
/**
* Generates a path to a temporary file location, ending with {#code path} parameter.
*
* #param path path suffix
* #return path to file inside a temp directory
*/
#NonCPS
String createTempLocation(String path) {
String tmpDir = pwd tmp: true
return tmpDir + File.separator + new File(path).getName()
}
/**
* Returns the path to a temp location of a script from the global library (resources/ subdirectory)
*
* #param srcPath path within the resources/ subdirectory of this repo
* #param destPath destination path (optional)
* #return path to local file
*/
String copyGlobalLibraryScript(String srcPath, String destPath = null) {
destPath = destPath ?: createTempLocation(srcPath)
writeFile file: destPath, text: libraryResource(srcPath)
echo "copyGlobalLibraryScript: copied ${srcPath} to ${destPath}"
return destPath
}
As it returns the path to the temp file, you can pass this to any step expecting a file name:
sh(copyGlobalLibraryScript('test.sh'))
for a file residing in resources/test.sh within your shared library.

stephenking's answer is more complete but for simple cases the following will do:
writeFile file: 'ps1FileInMySharedLibVarsFolder.ps1', text: libraryResource('ps1FileInMySharedLibVarsFolder.ps1')
powershell ".\\ps1FileInMySharedLibVarsFolder.ps1"

Related

Bazel: How to pass relative path of a file as an "args" to java_binary?

I have a file hello.txt that lives in src/main/resources folder.
I am using a java_binary rule and need to pass this hello.txt file as an argument.
java_binary(
name = "Hello",
srcs = glob(["src/main/java/**"]),
args = ["/Users/jdoe/repo1/libraries/myproj/src/main/resources/hello.txt"],
deps = [...],
)
The above works when I provide the full path, however it fails if I try with a relative path like src/main/resources/hello.txt.
How do I provide a relative path to the args attribute?
Your binary depends on the resource file hello.txt, but Bazel is not aware of this. Make hello.txt a data dependency of your java_binary, i. e. add the attribute data = ["src/main/resources/hello.txt"]. Bazel runs your executable in a sandbox, i.e. somewhere where your hello.txt is not present. The data dependency makes sure that the file is copied to the place where it is needed.

Bazel get location of external dependency as command line arg for py_binary

I need the path to external (or internal) dependency to pass it as an argument to a function inside. We need the location to the folder, not specific files. Also, sometimes, we need the path to the folder where a shared library, generated by cc_library.
Python file
import cppyy
cppyy.add_include_path('path/to/external/dependency/1')
cppyy.add_library_path('path/to/another/external/dependency/2')
cppyy.add_include_path('path/to/another/internal/dependency')
cppyy.include('file/in/external/dependency')
BUILD file
py_binary(
name = "sample",
srcs = ["sample.py"],
deps = [
"#cppyy_archive//:cppyy",
],
data = [
"#external-dependency//location:target",
"//internal-dependency/location:target2"
]
)
From https://docs.bazel.build/versions/master/external.html#layout:
You can see the external directory by running:
ls $(bazel info output_base)/external
How the paths in external actually look like really depends on the rule used for the archive.
For example, if it's declared using an http_file in the WORKSPACE file:
load("#bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
http_file(
name = "fenix",
urls = ["https://github.com/mozilla-mobile/fenix/archive/v76.0.0-beta.2.tar.gz"],
sha256 = "94050c664e5ec5b66cd2ca9f6a8b898987ab63d9602090533217df1a3f2dc5a9"
)
You will find that v76.0.0-beta.2.tar.gz file as external/fenix/file/downloaded:
user#host:~$ file $(bazel info output_base)/external/fenix/file/downloaded
/home/user/.cache/bazel/_bazel_user/761044447e04744e746cd54d0b4b5056/external/fenix/file/downloaded: gzip compressed data, from Unix, original size modulo 2^32 15759360

Read file content in WORKSPACE

I'm using container_pull in my WORKSPACE file. (It's part of bazel docker rules)
Here is what it looks like:
container_pull(
name = "base-image",
registry = "registry:9999",
repository = "base-image",
digest = "sha256:e6f44554a270025c578c0f91160d809735c2589baae80bafcdeebefb0c0b04b6",
tag = "1.1.0"
)
Howeve, there is a file containing the version of base-image, and I want it to be read from that file, instead of hardcoding in WORKSPACE.
How can I read a file content in WORKSPACE?
There's no direct way to read a file from the workspace file. The container_pull rule would have to add support for reading from a file.
A workaround is to put the file that contains the information into .bzl format, and load that from the workspace file.
Something like this:
versions.bzl:
BASE_IMAGE_VERSION = "1.1.0"
WORKSPACE:
load("//:versions.bzl", "BASE_IMAGE_VERSION")
container_pull(
name = "base-image",
registry = "registry:9999",
repository = "base-image",
digest = "sha256:e6f44554a270025c578c0f91160d809735c2589baae80bafcdeebefb0c0b04b6",
tag = BASE_IMAGE_VERSION,
)
Bazel does a similar thing in its own workspace file:
https://github.com/bazelbuild/bazel/blob/669a1a2634bdf267f890cf88833c9712d4e75016/WORKSPACE#L589

Dart const variables not bootstrapping correctly

I have the following Dart project structure:
myapp/
pubspec.yaml
pubspec.lock
asset/
packages/
build/
web/
MyAppClient.dart
Lookups.dart
Here is MyAppClient.dart:
library myapp;
part "Lookups.dart";
// Load/set environmental variables.
// At runtime SERVER_NAME should be "example.com"
String SERVER_NAME = const String.fromEnvironment(Lookups.ENV_VAR_SERVER_NAME);
// Construct all the URL globals used throughout the application. Each of these Strings should
// be visible everywhere in the "myapp" library
String SERVER_BASE_URL_PATTERN = "http://%s/" + Lookups.APP_NAME;
String SERVER_BASE_URL = SERVER_BASE_URL_PATTERN.replaceAll("%s", SERVER_NAME);
String DO_SOMETHING_URL = SERVER_BASE_URL + Lookups.DO_SOMETHING_SERVICE_ENDPOINT;
void main() {
// Expecting: http://example.com/myapp/doSomething, where "example.com" is the
// "serverName" env var loaded from String.fromEnvironment.
window.alert("DO_SOMETHING_URL = $DO_SOMETHING_URL");
}
And here is Lookups.dart:
part of myapp;
abstract class Lookups {
// Environmental variables.
static const String ENV_VAR_SERVER_NAME = "serverName";
// HTTP/AJAX/URL lookups.
static final String APP_NAME = "myapp";
static final String DO_SOMETHING_SERVICE_ENDPOINT = "/doSomething";
}
When I run pub build and try to run this in a browser (FF v22.0), the HTML does not display correctly and in Firebug I get an Illegal Arguments error. I have a feeling I am not instantiating my global Strings (DO_SOMETHNG_URL, etc.) correctly. Any ideas?
It looks like pub build does not support the -D command line arguments that are used by dart2js to handle environment variables. (You can file an issue).
$ pub build -DserverName=example.com
Could not find an option with short name "-D"

Downloading from /tmp folder in Heroku

I have a rake task that will generate a particular CSV file. I would like to be able to download that CSV file that is going to be placed in /tmp.
My application is hosted in Heroku. How can I download that CSV file?
If you just want to do a one off download, you could try using heroku exec. The exec command allows you to create an SSH connection to a dyno - https://devcenter.heroku.com/changelog-items/1112
First, figure out the file path. You can run bash, then do usual bash commands like ls:
heroku ps:exec -a <myapp> bash
Next, use cat to read the file, and pipe the output to a local file:
heroku ps:exec -a <myapp> cat tmp/myfile.csv > mylocal.csv
The /tmp directory on Heroku is exactly that – temporary. Even if you store the file in the /tmp file, it won't be persisted for long enough that any users will be able to access it. Instead, you should look into an integrated storage solution like Amazon AWS.
With that in place, your users should be able to access those CSV files directly from your storage host without needing to tie up any Heroku dynos/resources.
why is it necessary to place it in tmp folder? if you generate something it has to be important file not temporal one...
solution is easy, just setup your rake task in a way when your file will be saved into public directory (or subdirectory of public directory)
and then you can open/download your export.csv using
http://your-domain/[subdirectory-in-public-directory]/export.csv url
Files in the tmp directory are emptied everyday, tmp directory lives #:
/app/tmp
where app is the root directory
To download files from it you can read the file and convert it into a base 64 and send it back to the client as a data URL:
Server:
let filePath = path.join(__dirname, '..', '..', 'tmp', fileName);
fs.readFile(filePath, {encoding: 'base64'}, function (err, data) {
if (!err) {
let returnData = `data:${mimeType};base64,` + data;
res.json({fileName: fileName, displayName: displayName, base64: returnData})
} else {
console.log(err);
}
});
Client side:
function b64toBlob(dataURI) {
var byteString = atob(dataURI.split(',')[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type: 'image/jpeg' });
}
var blob = b64toBlob(res.data.base64);
var blobUrl = URL.createObjectURL(blob);
var link = document.createElement("a"); // Or maybe get it from the current document
link.href = blobUrl;
link.download = res.data.displayName;
document.body.appendChild(link)
link.click()

Resources