Download build drop from hosted Team Foundation Service - continuous-integration

Using the hosted Team Foundation Service at tfs.visualstudio.com, one has the option in a Build Definition to "Copy build output to the server" which creates a zip of the drop folder that can be downloaded over https via team web access. I really need to download this drop automatically, so I can chain input to the next stage in my build pipeline.
Unfortunately, the drop URL is not obvious, but can be created using the TfsDropDownloader.
TL;DR - I can't get the TfsDropDownloader to work, I'm hoping someone else has used this tool or a similar method to succesfully download a drop from https://tfs.visualstudio.com
Using the command line TfsDropDownloader.exe I can do this:
TfsDropDownloader.exe /c:"https://MYPROJECTNAME.visualstudio.com/DefaultCollection" /t:"ProjectName" /b:"BuildDefinitionName" /u:username /p:password
...and get an empty zip file with the correct build label name of the last successful build e.g. BuildDefinitionName_20130611.1.zip
Running the source code in the debugger, this is because the URL that is generated for downloading:
https://tflonline.visualstudio.com/DefaultCollection/_apis/resources/containers/804/drop/BuildDefinitionName_20130611.1.zip
..returns a content type of application/json, which is unsupported. This exception is swallowed by the application, but not before the empty zip file is created.
Is it possible the REST API on Team Foundation Service has changed in some way so the generated URL is no longer correct?
Note that I am using the "alternate credentials" defined on my Team Foundation Service account (i.e. not my live ID) - using anything else gets me TF30063: not authorized.

I got it working by using alternate credentials, but I also had to access the REST API via a different path.
The current TfsDropDownloader builds a URL that looks like this:
https://project.visualstudio.com/DefaultCollection/_apis/resources/containers/804/drop/BuildDefinitionName_20130611.1.zip
This returns empty JSON whenever I try to use it. I'm definitely authenticated, because if I tweak the URL to:
https://project.visualstudio.com/DefaultCollection/_apis/resources/containers/804/drop
I get a nice JSON listing of every single file in the drop, but no zip.
From spying on the SSL traffic to https://tfs.visualstudio.com with Fiddler I saw that clicking the "Download drop as zip" link I can see that there is another endpoint at:
https://project.visualstudio.com/DefaultCollection/ProjectName/_api/_build/ItemContent?buildUri=vstfs%3a%2f%2f%2fBuild%2fBuild%2f639&path=%2Fdrop
...which does give you a zip. The "vstfs%3a%2f%2f%2fBuild%2fBuild%2f639" portion is the URL encoded BuildUri.
So I've changed my version of GetServerPath in the TfsDropDownloader source to do this:
private static string GetServerPath(TfsConnection collection, IBuildDetail buildDetail)
{
var downloadPath = string.Format("{0}{1}/_api/_build/ItemContent?buildUri={2}&path=%2Fdrop",
collection.Uri,
HttpUtility.UrlPathEncode(buildDetail.TeamProject),
HttpUtility.UrlEncode(buildDetail.Uri.ToString()));
return downloadPath;
}
This works for me for the time being. Hopefully this helps someone else with the same problem!

Related

Dredd can't find my API documentation, how do i tell it where it is if it's not on my local drive (it's on apiary.io server)

I am using the Dredd tool to test my API (which resides on apiary.io).
Question
I would like to provide dredd with a path to my documentation (it even asks for it), however my API doc is on apiary.io but i don't know the exact url that points to it. What would be the correct way to provide dredd with the API path?
What did work (but not what i'm looking for)
Note: I tried downloading the api to my local drive and providing dredd with a local path to the file (yml or apib) which works fine (yay!), but i would like to avoid keeping a local copy and simply providing dredd with the location of my real API doc which is being maintained on the apiary server.
How do I do this (without first fetching the file to local drive)?
Attempts to solve this that failed
I also read (and tried) on the following topics, they may be relevant but i wasn't successful in resolving the issue
- Using authentication token as environment variable
- Providing the domain provided by apiary.io//settings to dredd
- Providing the in the dredd command
all of these attempts still produces the same result, Dredd has no idea where to find the API document unless i provide a path in my local computer to the file (which i have to download or create manually on my computer first).
Any help is appreciated, Thanks!
If I understand it correctly, you would like to use dredd and feed it using the API description document residing on Apiar.io platform, right?
If so, you should be able to do that simply calling the init command with the right options:
dredd init -r apiary -j apiaryApiKey:privateToken -j apiaryApiName:sasdasdasd
You can find the private token going into the Test section of the target API (you'll find the button on the application header).
Let me know if this solves the problem for you - I'll make sure to propagate this and document it accordingly on our help page
P.S: You can also use your own reporter - in that case, simply omit -r apiary when writing the command line parameters.
You can feed Dredd not only with a path to file on your disk, but also with an URL.
If your API in Apiary is public, the API description document (in this case API Blueprint) should have a public URL. For example, if you go to http://docs.apiblueprintapi.apiary.io/, you can see on the left there is a Download link. Unfortunately, the link is visible only for users who do not have access to the editor of the API, so you can’t see the link if you’re owner of the API. Try to log out from Apiary and the link should appear:
Then you can feed Dredd with the link:
$ dredd 'http://docs.apiblueprintapi.apiary.io/api-description-document' 'http://example.com:8080/api'
I agree this isn’t very intuitive and since you’re not the first one to come up with this, I think we’ll think of some ways how to make it easier.
If your API isn't public then unfortunately there's no way to get the URL as of now. However, you can either use GitHub Sync or Apiary CLI to get the file on your disk in an automated manner.

Google REST API v3 - Revisions:list vs "Show more detailed revisions"

I need to get the detailed list of the revisions for a Google Document.
When using the Google API Explorer on:
GET https://www.googleapis.com/drive/v3/files/{fileId}/revisions
I get only the non-detailed list.
Which is the API to call (or the parameter to set) in order to get something similar to what can be seen by pressing Show more detailed revisions?
Update:
I tried to "sniff" the browser traffic and I realized that Google Drive periodically requests the revision list to the URL:
https://docs.google.com/spreadsheets/d/{fileId}/revisions/history?id={fileId}&start=1&end=-1&zoom_level=0&token={token}
When clicking on Show more detailed revisions, the previous URL becomes:
https://docs.google.com/spreadsheets/d/{fileId}/revisions/history?id={fileId}&start=1&end=-1&zoom_level=1&token={token}
(the zoom_level parameter changes from 0 to 1)
I cannot find anything like that on the API reference, though. It seems that such an URL has to be invoked manually.
Therefore, I manually generated a token for the drive scope, manually checked it in order to keep it fresh and manually invoked that URL, in order to see what happened. Unfortunately, I got the following error on the browser:
Impossibile aprire il file in questo momento.
Verifica l'indirizzo e riprova.
which roughly means:
Unable to open the file at the moment.
Please verify the address and try again.
May somebody point me towards the right direction?
In the "Try it" section of the API there is a field called "fields". In there you can select the files you need from the response. If you write "kind,revisions" you will get the complete information or you can use the "fields editor" to select the fields you need.

Play! Framework 2.1.3 pdf problems

so I am working on a school project in which we have designed a web application that takes in much user info and creates a pdf then should display that pdf to the user so they can print it off or save it. We are using Play! Framework 2.1.3 as our framework and server and Java for the server side. I create the pdf with Apache's PDFbox library. Every thing works as it should in development mode ie launching it on a localhost with plays run command. the issue is when we put it up to the server and launch with plays start command I it seems to take a snapshot of the directory (or at least the assets/public folder) which is where I am housing the output.pdf file/s (i have attempted to move the file elsewhere but that still seems to result in a 404 error). Initially I believed this to be something with liunx machine we were deploying to which was creating a caching problem and have tried many of the tricks to defeat the browser from caching the pdf
like using javascript to append on a time stamp to the filename,
using this cache-control directive in the play! documentation,
"assets.cache./public/stylesheets/output.pdf"="max-age=0",
then I tried to just save the pdf as a different filename each time and pass back the name of that file and call it directly through the file structure in the HTML
which also works fine with the run command but not the start.
finally I came to the conclusion that when the start command is issued it balls up the files so only the files that are there when the start command is issued can be seen.
I read the documentation here
http://www.playframework.com/documentation/2.1.x/Production
which then I noticed this part
When you run the start command, Play forks a new JVM and runs the
default Netty HTTP server. The standard output stream is redirected to
the Play console, so you can monitor its status.
so it looks like the fact that it forks a new JVM is what is causing my pain.
so my question really is can this be gotten around in some way that a web app can create and display a pdf form? (if I cannot get this to work my only solution
that I can see is that I will have to simulate the form with HTML and fill it out from there) --which I really think is a bad way to do this.
this seems like something that should have a solution but I cannot seem to find or come up with one please help.
i have looked here:
http://www.playframework.com/documentation/2.1.x/JavaStream
the answer may be in there but Im not getting it to work I am pretty novice with this Play! Framework still
You are trying to deliver the generated PDF file to the user by placing it in the assets directory, and putting a link to it in the HTML. This works in development mode because Play finds the assets in the directory. It won't work in production because the project is wrapped up into a jar file when you do play dist, and the contents of the jar file can't be modified by the Play application. (In dev mode, Play has a classpath entry for the directory. In production, the classpath points to the jar file).
You are on the right lines with JavaStream. The way forward is:
Generate the PDF somewhere in your local filesystem (I recommend the temp directory).
Write a new Action in your Application object that opens the file you generated, and serves it instead of a web page.
Check out the Play docs for serving files. This approach also has the advantage that you can specify the filename that the user sees. There is an overloaded function Controller.ok(File file, String filename) for doing this. (When you generate the file, you should give it a unique name, otherwise each request will overwrite the file from a previous request. But you don't want the user to see the unique name).

How entity edit URL from within plug-in in MS Dynamics CRM 4.0

I would like to have a workflow create a task, then email the assigned user that they have a new task and include a link to the newly created task in the body of the email. I have client side code that will correctly create the edit URL, using the entities GUID and stores it in a custom attribute. However, when the task is created from within a workflow, the client script isn't run.
So, I think a plug-in should work, but I can't figure out how to determine the URL of the CRM installation. I'm authoring this in a test environment and definitely don't want to have to change things when I move to production. I'm sure I could use a config file, but seems like the plug-in should be able to figure this out at runtime.
Anyone have any ideas how to access the URL of the crm service from within a plug-in? Any other ideas?
There is no simple way to do this. However, there is one.
The MSCRM_Config is the deployment database that handle physical deployment properties, like the URL from which users are accessing the CRM deployment. The url that you might want is the one stored in "ADWebApplicationRootDomain", in the MSCRM_CONFIG.dbo.DeploymentProperties table. You may need some permission to access this database.
Note that this doesn't work in a deployment that is an Internet Facing Deployment.
Another way could be to query the discovery service to retrieve the same information (in the case that you are on the Online edition of MSCRM4).
What do you mean by "change things"?
If you create a custom workflow assembly, you can give it a server url input. Once you register it with CRM, you can simply type in the server url when you configure the workflow. You'll have to update the url for any workflows that use the custom workflow assembly once you move to production, but you'll only have to do that once.
My apologies if this is what you meant you wanted to avoid.
Edit: Sounds like you may be able to use the CustomConfiguration attribute when you register the plugin. Here's some more info.
http://blogs.msdn.com/crm/archive/2008/10/24/storing-configuration-data-for-microsoft-dynamics-crm-plug-ins.aspx
String Url = ((string)(Registry.LocalMachine.OpenSubKey(
"Software\\Microsoft\\MSCRM").GetValue("ServerUrl"))
).Replace("MSCRMServices", "");

ClickOnce: How do I pass a querystring value to my app *through the installer*?

My company currently builds separate MSI's for all of our clients, even though the app is 100% the same across the board (with a single exception, an ID in the app.config).
I would like to show them that we can publish in once place with ClickOnce, and simply add a query string parameter for each client's installer.
Example: http://mysite.com/setup.exe?ID=1234-56-7890
The issue that I'm having is that the above ("ID=1234...") is not being passed along to the "myapplication.application". What is happening instead is, the app is being installed successfully, and it is running the first time with an activation context, but the "ActivationUri" does not contain any query string values.
Is there a way to pass query string values FROM THE INSTALLER URL to the application's launch URL? If so, how?
After much searching (and discussing), the answer is simply that the current version of ClickOnce doesn't work that way. The installer does not pass the URL onto the application up it's first run.
Here is what I have done for a workaround (and it works great).
Change my setup package to have all of the required files uncompressed and loose (as apposed to using a CAB file, or embedding them in the installer).
Make an ASP.NET application (using Routing for URL handling) that listens for a request to "mysite.com/Installer/00123/Setup.exe"
Note: the route should listen for "/Installer/{ID}/*" where {ID} is 5 digits.
There is actually no directory called "00123", but rather, I'm using ASP.NET Routing to pickup those requests and then I map it to my actual directory that has the installer file in it.
I then hijack the request (parse the setup.exe to find the embedded URL that tells the installer program where to find the rest of the files... I then replace "/00000/" with the request URL that the user went to - in this case "00123".
As each file is being requested, I know which "version" of the file to send, because the ClickOnce Installer will be looking for "mysite.com/Installer/00123/SomeFile.dll" (or whatever).
Instead of using a 5-digit ID, you could use a GUID... it's up to you.
This solution works great for our organization... we currently have 37 clients who require unique customizations to their installer package, but we only have to actually build and publish ONE installer package and simply use the hijack method above.
At this point we have placeholders that we swap out so that it's easy to customize installers for as many clients as we want.
Example: in the app.config file we have displayName="{OrgName}" which is automatically replaced by one of the values in the database.
For me, "http://mysite.com/myapplication.application?id=1234-56-7890" seems to do the trick.
I know this is outdated, but I just wanted to provide the current solution.
To retrieve querystring parameters in a ClickOnce application:
Point the app/download/setup link to the application (with .application extension), not "setup.exe"
Add this function to your ClickOnce application to retrieve the querystring parameter collection:
private NameValueCollection GetQueryStringParameters()
{
NameValueCollection nameValueTable = new NameValueCollection();
if (ApplicationDeployment.IsNetworkDeployed)
{
string queryString = ApplicationDeployment.CurrentDeployment.ActivationUri.Query;
nameValueTable = HttpUtility.ParseQueryString(queryString);
}
return (nameValueTable);
}
Then to get a querystring param value:
var querystringParams = GetQueryStringParameters();
string param_value = querystringParams["param_name"];
Don't forget the Usings:
using System.Collections.Specialized;
using System.Deployment.Application;
using System.Web;
Source: https://learn.microsoft.com/en-us/visualstudio/deployment/how-to-retrieve-query-string-information-in-an-online-clickonce-application?view=vs-2019

Resources