Lesson 16 of 17
TeamCity CI and Artifacts
In this lesson
On a TeamCity server with a project that runs RSpec and Cucumber tests, Roy Osherove creates a CI build configuration, points out where it would share artifacts with other builds, connects it to a git repository on GitHub and adds a simple echo build step. He adds a VCS trigger so every check-in starts a build, and goes over the other triggers, such as a schedule, another build finishing, branches and retries, which he says are not for a CI build. He then replaces the step with a rake build step (external link, opens in new tab) that runs the project's rake file, the Ruby version of make, so TeamCity only triggers rake and does not need to know where the tests are, and he keeps the rake file in source control rather than in TeamCity, where it would not be versioned.
Transcript
[00:04] (external link, opens in new tab) So this is a TeamCity server and I've already set up a one build in a project called test one but it would be the name of your project. And in this build what's going on is that every time I check in I can see the different files that were checked in. I can see the diffs between them. For example the gem file here changed. So it's very easy to see the differences. I can see the tests that were passed.
[00:36] (external link, opens in new tab) So this is an example of feature tests. These are all the test that passed. This is running RSpec and Cucumber. And what we're going to do, we're going to create a continuous integration of our own. And this is what it looks like. If I go to administration under projects in the root project I can create either a sub project or build configuration. So I'm going to create a build configuration here.
[01:07] (external link, opens in new tab) I'm going to call it CI 2 but it would be the first one. I would just call it CI continuous integration. And I don't need to use the other stuff here for now. But when I want to start sharing artifacts to other builds, this location here is where I would share them and I would say share everything under the root to to other builds and then other builds can pick and choose or I would say just give me everything under lib which is also possible
[01:40] (external link, opens in new tab) But for now we don't have other builds so we don't need that. So, I'm going to create a build configuration. CI2 and VCS settings is where I decide what source control to use. I've created a source control called local git. But I'll show you what it's like to to have source control that's connected to git. So, I have git here. I can connect to team system to anything. I can give it a name remote git.
[02:14] (external link, opens in new tab) And I can go to to GitHub and say, okay, let me get let me get this. So I'll use the TDD demo for the source control. And what we'll do now is I need the fetch URL. I can say GitHub rubd demo.get get
[02:45] (external link, opens in new tab) And I think that should be enough and I can test the connection and see what happens. Connection successful and I can set some other things. For example, by default it would look and check in check trigger stuff every 60 seconds. So it will if multiple people check in, it will gather their their projects. But I can say for demo purposes just just listen every 10 seconds. I can choose to clean all the files.
[03:17] (external link, opens in new tab) I can have a lot of different branches that I want to get here. By default, I'm just getting the master branch. I'm getting everything. So I'm attaching to the remote automatically on the server, which is what I want. I can label the branch if I want to. And now I want to add a build step. So a build step this is the stuff that either triggers our build script (external link, opens in new tab).
[03:48] (external link, opens in new tab) This is the stuff that happens after checkout or after git get fetch. In our case I can just as an example I can just say that we can run the script. Can we just say echo in Unix? Just say echo hello from the build step. Okay, if we did that we can u by default give it say a hello world.
[04:20] (external link, opens in new tab) We can save that and we're ready to run our builds. So this is the CI2. If I click here, I can run it. It's getting the changes. It's updating the sources. and success. Obviously, we haven't done anything yet, but I can look at the build log. I can look just at the tail if it's still running. I can see a live view of the build log.
[04:51] (external link, opens in new tab) I see step one, hello world, right here. You can look at the important messages if there are any errors. Can look at the tree view, which is readable. Okay, so far so good. That's the first build. Let's trigger this build. Edit settings. I want it to trigger automatically. So I go to the build triggers in the configuration settings. I add a new trigger. And I can have many different triggers. For example, VCS trigger is a trigger that makes sure that every once every time someone checks in, build gets triggered automatically.
[05:29] (external link, opens in new tab) That's what we want. I can also choose it's a build that happens every night at 12 or every day at 3:00 a.m. I can have this build automatically start when a different build configuration finishes. That's important for when I want to have the build wave. So I would like to have continuous integration and then slow builds automatically run. I can automatically run builds on branches that people have made
[06:02] (external link, opens in new tab) To make sure that that branch passes. And that's a bit more complicated for now. We won't touch that too much. I can have a retry. A retry is good if your build fails, but it if it passes one of three builds, then you're good. That's definitely not for a CI build. CI build should be passing immediately. Okay. By default, we can just use the default rules. But if I wanted to only check in on specific folders that change, I can add trigger rules here and say only only trigger this build if something that's not a config file change.
[06:42] (external link, opens in new tab) But I want to trigger on everything. Okay, so I saved it. Now, if I go to my source control and I just try to push. Okay, let's do a touch. What do we say? Gem file status that change. Oh, okay. V something.xt.
[07:15] (external link, opens in new tab) Hey, let's go check something in. I'll push it to the folder. Okay. Hopefully that's okay. Now, now if I just look here and I don't do anything, hopefully this should be detected. I don't know what's happening now. We have we have a situation.
[08:03] (external link, opens in new tab) Okay. So, this was running 3 minutes ago, but now I should see pending here because this build was also triggered. I al already have a trigger for the previous build that I have with tests and this one triggers as well. So you can see that it triggers does nothing and since I only have a single build agent installed in this machine I can see it here. Then this build went into the queue and then when that one finished this one started. Okay. So now let's say that we want to run
[08:37] (external link, opens in new tab) A rake file (external link, opens in new tab). And this is important because we want a rake file to be our build script. So in this case, my rake file only has two only has two tasks. Now if you don't know what a rake file is, it's the Ruby version of make. It's the way to automate whatever we want. So by default, I would create just a structure of tasks.
[09:08] (external link, opens in new tab) >> >> I have a default task which is what happens when you just say rake and you have a rake file and but here I say default is depending on a task called spec and a task called features. This is the spec task it's based on a rake task from RSpec. So I have RSpec core rake task and then I configure it to say just run string calculator specs for now.
[09:40] (external link, opens in new tab) I can rename it whatever I want. Of course I can say spec or string calc and I give it the options of formatting things for documentation and the same for cucumber. I give it a name features and I say the options are to run every just the Sinatra features and I want it to format in a nice greedy way and then I just say that the default task depends on spec and features. So if I just say right here directly
[10:13] (external link, opens in new tab) I should see this. Okay. And that's good for me because now I know how to run the test and where they are. I don't want the TeamCity to work to know where the tests are. I could have had TeamCity run a command line that runs RSpec and Cucumber. That's not what I want. I want TeamCity to to have a a blind trigger that just triggers rake. So, if I go back to TeamCity and I go to the build steps and I I'm going to remove this, disable it for now.
[10:46] (external link, opens in new tab) Add a build step and say I want a rake file not Gradle rake file can call it just rake and the path to the rake file I don't have to give it by default it will use the default rake file name I can I can enter the rake file content here but remember not a good idea because this is not versioned Okay. So if I the rake file that that is good for this version might not be good for the previous versions.
[11:23] (external link, opens in new tab) Anything else I need to do here? Do I want to use bundler or not? I have I have a gem file. So I'm going to use bundler but if you don't you don't have to use bundle exec. I don't need test unit as dependencies. I just want rspec and cucumber. And I'm going to save and I can I guess just delete that. >> >> Now I just have the rake task and I can go to projects and
[12:02] (external link, opens in new tab) So now what we should be go seeing is that it checks out and it ran the test and I can see the test passing just like I did in the command line.