Job re-run not triggering dependent jobs

I am new to Concourse. Read most of the docs, and just finished the Pluralsight course “Getting Started with Concourse”.

I started out with a simple job (mod3-pipeline-1 in that class). I don’t want to reproduce the entire thing because it is probably copyrighted but here is the essense. The pipeline is
source-code — unit-test — source-code — package-app --artifact-repository — deploy-app.

  • artifact-repository resource is an S3 bucket
  • Source code resource is a Git repository
  • unit-test is the first job, and pulls down the source code and runs the unit tests then shows the files created.
  • package-app builds the source code and tars up the built artifacts, and sends them to artifact-repository
  • deploy-app gets the tar file from the S3 bucket and extracts it.

Package app starts with:
- name: package-app
- get: source-code
passed: [unit-test]
trigger: true

The first time, the pipeline worked fine. As I change things and I want to rerun the pipeline to test it out, rerunning unit-test does not trigger package-app. My gut is telling me this is because source-code didn’t change, but… the job specifies that package-app should run when unit-test succeeds, but it doesn’t.

How do I get the entire pipeline to run again from the first job even if nothing changed? there HAS to be a way to do that. Otherwise, how do you tell if a job is still valid? What if someone deletes the app from the bucket and it needs to be recreated?

Side note, the whole concept of having to start a job, as opposed to running “the pipeline” seems wrong to me. What would you do if there were multiple parallel jobs in the beginning of the pipeline? Create an artificial first job that does nothing that they are all dependent on? Semantically that’s icky.


Concourse pipelines are only “pipelines” as a result of passing resources from job to job and putting passed and trigger options on them otherwise they are just a disconnected collection of jobs. This means the only way to automatically trigger any job is for an input resource to change and be configured to trigger the job.

Its a little difficult to tell what going on in your example without seeing the pipelines. If the unit test job is configured with

- get: source-code
  trigger: true

then I would expect it to start automatically when a new commit is pushed to the repo then once unit tests pass the next job (package-app) would start. If you manually start the unit test job again without changing the source repo then the package-app job won’t start automatically because the input resource that it triggers on hasn’t changed.

There isn’t a built-in feature of Concourse to run a “pipeline” all the way through end-to-end. I don’t really understand what you mean by needing the ensure a job is still valid. A job is in essence just a series of steps that get specific versions of resources, manipulate them in some way, then put updated versions to resources. A job is only as valid as the resources it interacts with. If the job creates something in S3 that is subsequently deleted then running the job again with recreate it. If the job requires something that gets deleted the job will fail to start. Each build of a job is independent of any previous build.

I know from using Concourse to deploy infrastructure and platforms (like Cloud Foundry) that sometimes there is a need to run the whole pipeline all the way through. I’ve had success setting up a semver resource with a job at the start of the pipeline that bumps the version when you run it. Then make every subsequent job trigger off of changes to the semver. This means that you can manually run the “bump” job to set off an end-to-end run of all the jobs in order.

To your final point, I mentioned before that a “pipeline” in Concourse is just a collection of jobs that are connected by the resources they use. There is nothing stopping you from having multiple jobs that run in parallel at the start of a pipeline. You can just have them all trigger true on the same resource with no passed constraints. The concepts of “fanning in” and “fanning out” are quite common in pipeline-writing.

Thanks for replying. Yes, the unit-test job is triggered by source code changes:

  • name: unit-test
    • get: source-code
      trigger: true
    • task: run-tests

But if you’re telling me that running unit-test by changing the source-code will trigger package-app, but running unit-test manually will not, then there’s no way to test the pipeline or recreate the same artifact.

Maybe I don’t understand the implications of “passed” and “trigger”. Given:

  • name: package-app
    • get: source-code
      passed: [unit-test]
      trigger: true

Does that mean the real trigger to running this job is the source code change, not the unit tests passing? And that the unit tests passing is merely a gate, not a trigger?

Is it smart enough to mean "If the source code changes, don’t run package-app unless the unit-tests job has been run and succeeded SINCE THE SOURCE CODE CHANGE? Or is it more like two layers of triggers, where the source code changing moves it into one finite state, then from there it can only enter the triggered state by the unit-test succeeding?

Thanks. I appreciate any clarifications you can offer.

Passed constraints act as a filter on the list of versions that are available to a job.

- name: package-app
  - get: source-code
    passed: [unit-test]
    trigger: true

means that when the package-app job looks for a new version of the source-code resource it will be able to choose from all the versions found by the check script in the resource minus any that have failed the unit-test job. By default it will pick the latest of these versions. The trigger: true tells it to start automatically if a new version matching the passed constraints is detected.

The “real” trigger in Concourse is always resources changing. The result of jobs just impacts which versions of resources are visible to future jobs.

So if a change is made to source-code, then unit-test will trigger automatically then, if it passes, that new version of the resource will become visible to the package-app job which would then trigger. If you then manually run the unit-test job again without making a change to the source-code repo then the input version of the resource will remain unchanged. Since package-app has already triggered automatically with that version it won’t trigger automatically again even though the preceding job has run.

It’s worth noting that this behaviour changed a little bit in Concourse v6 but the essence remains the same. I think the release notes can explain this change better than I ever could.

1 Like

Excellent explanation. Thank you so much for taking the time. It makes a lot more sense now.

what I’ve ended up doing to run an entire pipeline is to have a file called .trigger_file in the top directory of each repository and then I simply write the date and a message into the file and commit it back.

I need this so that I can have one pipeline trigger another.
To make this work without pulling the entire contents of the repository, my script runs
git clone -n --depth 1
git reset HEAD ~~~otherwise git thinks I deleted everything
git add .trigger_file
git commit
git push