Leveraging CircleCI API to include build logs in Slack notifications

Leveraging CircleCI API to include build logs in Slack notifications

The Slack Orb allows you to send notifications, and customize the message sent. In most cases, this is used to indicate a build status, such as if it failed.

While the above is helpful, it still requires you to navigate back to the build to get information about why it failed.

Wouldn’t it be nice if you could include the last few lines of the log output with your Slack message? This could help easily identify the issue, such as the exit code reason or specific error messages. Maybe something like this…

The following guide will provide step by step details on setting this up!

Requirements

  1. This guide utilizes Orbs, so you will need to be on at least version 2.1.
  2. The API calls and data manipulation are done in bash so your image will need to support that (including utilizing jq).
  3. While this should work out of the box, you may need to adjust slightly to account for how your steps output values.

Setup the Slack orb

Information on setting up the Slack orb.

Once the above is done you will need to ensure you include it within your config.yml file with the following:

orbs:
  slack: circleci/slack@4.2.1

Configure Environment Variables

Both the Slack orb and the run steps contained in this guide require some environment variables to be set. These can be done at the project level, or, if you plan to use it across projects – set these up in a context.

Variable Name Description
CIRCLE_API_TOKEN This will be a personal API token.
SLACK_ACCESS_TOKEN The OAuth token acquired through the Slack setup steps.
SLACK_DEFAULT_CHANNEL If no channel ID is specified, the Slack orb will attempt to post here.

The SLACK_ACCESS_TOKEN and SLACK_DEFAULT_CHANNEL should already be set from following the “Setup the Slack orb” step above.

Add the run step that collects and prepares log data

The snippet below should be able to be added as one of the last steps in the job you want to be notified in. While you can copy and paste it, you may want to adjust some parts.

  1. Remove or adjust jq install lines accordingly (first two steps under command). If you already have it installed on the image, remove them. If utilizing an alpine image, adjust to apk.
  2. On line 9 of the command step, adjust the amount of rows from the log you want returned. It’s set to 10, tail -n 10, so adjust 10 accordingly.
- run:
    when: on_fail
    name: Generate last log lines for slack message
    command: |
      sudo apt-get update
      sudo apt-get install jq
      API_URL=$(echo $CIRCLE_BUILD_URL | cut -d/ -f4-7)
      FAILED_STEP=$(curl "https://circleci.com/api/v1.1/project/${API_URL}?circle-token=${CIRCLE_API_TOKEN}" | jq '.steps | .[] | flatten | map(select(.status? == "failed")) | .[] | {allocation_id, step}')

      ALLOCATION_ID=$(echo "${FAILED_STEP}" | jq -r '.allocation_id')
      STEP=$(echo "${FAILED_STEP}" | jq -r '.step')
      curl -o slack_response.txt "https://circleci.com/api/v1.1/project/${API_URL}/output/${STEP}/0?file=true&allocation-id=${ALLOCATION_ID}&circle-token=$CIRCLE_API_TOKEN"
      sed -i 's/\r$//g' slack_response.txt
      SLACK_MESSAGE=$(cat slack_response.txt | tail -n 10 | sed '$!s/$/\\n/' | tr -d '\n')
      echo $SLACK_MESSAGE
      echo "export SLACK_MESSAGE='${SLACK_MESSAGE}'" >> $BASH_ENV

Invoke the Slack orb and utilize the message generated

The below step should go right after the above step. You can adjust as needed, but you will likely want to keep the following block:

{
  "type": "section",
  "text": {
    "type": "mrkdwn",
    "text": "```${SLACK_MESSAGE}```"
    }
}
           

As the above ensures the log message is included in the Slack message. Add this below the “Generate last log lines for slack message” step that you added in the last section.

- slack/notify:
    event: fail
    custom: |
      {
        "blocks": [
          {
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": "```${SLACK_MESSAGE}```"
            }
          },
          {
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": "Build failed, above is last few lines of the log"
            },
            "accessory": {
              "type": "button",
              "text": {
                "type": "plain_text",
                "text": "Click Me",
                "emoji": true
              },
              "value": "click_me_123",
              "url": "${CIRCLE_BUILD_URL}",
              "action_id": "button-action"
            }
          }
        ]
      }

:tada: That’s it! You should now receive the last few log lines of the failed step as part of your Slack notification.

Resources

This guide stemmed from a previous solution I provided a customer, which was a bash script that did something similar.

If helpful to see how this would look in a config.yml see the following gist:

5 Likes

@nbialostosky Thanks for posting this, very useful and something I have had on my to-do list to add to our deployments for a while.

One minor note is that the example config.yml on your github needs indents added for lines Lines 19-33 for it to be accepted by the circleci yaml parser. Correct indent in this post though.

Thanks for calling this out! I have updated the gist accordingly, and should be valid now!

1 Like

Thanks for this! I’ll be implementing this today, but I have a followup question: Is it possible to calculate the URL of a log file artifact for the failed job? The URL subdomain is a mix of the CIRCLE_BUILD_NUM and some other number. https://{Build Num}-{???}-gh.circle-artifacts.com/0/{file name}. My goal would be to include a button in the Slack message to directly download the log file.

Hi @jakeatoms, great question!

You can actually just make a secondary API call to the artifacts endpoint, I wrote a support article on this:

So you would add this run step after your artifact upload step and then include it in the Slack custom message you send. Hope that helps clarify!

1 Like

Hi @nbialostosky

Many thanks for this solution! I almost got it to work. The curl "https://circleci.com/api/v1.1/project/${API_URL}?circle-token=${CIRCLECI_API_TOKEN}" | jq part failed with this error : parse error: Invalid numeric literal at line 1, column 10.

I observed that the curl output itself is not in valid json format. Is this the reason why this error showed up? I am really surprise seeing all of the gibberish below when I redirected curl output to a file.

<!DOCTYPE html>
<html><head><title>Continuous Integration and Deployment</title><meta content="text/html; charset=utf-8" http-equiv="Content-Type"><meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"><meta content="width=device-width, initial-scale=1" name="viewport"><meta content="CircleCI" name="apple-mobile-web-app-title"><meta content="Hosted Continuous Integration for web applications. Set up your application for testing in one click, on the fastest testing platform on the internet." name="description"><link href="https://dmmj3mmt94rvw.cloudfront.net/favicon-undefined.ico" rel="icon" type="image/png"><link href="https://dmmj3mmt94rvw.cloudfront.net/assets/css/app-2aee31877418f72a53af30f3775829e4.css" rel="stylesheet" type="text/css"><script type="text/javascript">var circleEnvironment = "production";var circleHost = "circle-www-api-v1-57b68684b4-nb92n";var current_manifest_version_key = "frontend-releases/v3/3e3971eb539a.json";var segmentWriteKey = 'AbgkrlzMkHbwvrXnxHh35';var CSRFToken = 'k5XSJUk1-mIOV9vkJad1kVpUTcF1KXBujEkWV-xb168yGdvBqu';var OAuthCSRFToken = '1jkA-ONu6h521PRuVdZwWBV0uz4ixoIixe7K1fMWGFb8W03kye3ZBG';</script><meta content="{&quot;assetsRoot&quot;:&quot;https://dmmj3mmt94rvw.cloudfront.net&quot;,&quot;enterprise&quot;:false,&quot;enabled_auth_providers&quot;:[&quot;github&quot;,&quot;bitbucket&quot;],&quot;analytics_enabled&quot;:true,&quot;githubHttpEndpoint&quot;:&quot;https://github.com&quot;,&quot;is_1_0_enabled&quot;:false,&quot;enabled_code_providers&quot;:[&quot;github&quot;,&quot;bitbucket&quot;],&quot;support_email&quot;:&quot;sayhi@circleci.com&quot;,&quot;support_enabled&quot;:false,&quot;pusher&quot;:{&quot;key&quot;:&quot;1cf6e0e755e419d2ac9a&quot;},&quot;user_session_settings&quot;:null,&quot;auth_protocol&quot;:&quot;https&quot;,&quot;current_user&quot;:null,&quot;zuora_urls&quot;:{&quot;hosted_url&quot;:&quot;https://www.zuora.com/apps/PublicHostedPageLite.do&quot;,&quot;signature_url&quot;:&quot;https://api.zuora.com/rest/v1/rsa-signatures&quot;,&quot;script_url&quot;:&quot;https://static.zuora.com/Resources/libs/hosted/1.3.0/zuora-min.js&quot;},&quot;status&quot;:404,&quot;logging_enabled&quot;:false,&quot;log_channels&quot;:false,&quot;instrument&quot;:false,&quot;bitbucketClientId&quot;:&quot;4DMqkNUJUMcdfnFtDU&quot;,&quot;is_2_0_enabled&quot;:true,&quot;githubClientId&quot;:&quot;78a2ba87f071c28e65bb&quot;,&quot;env&quot;:&quot;production&quot;,&quot;auth_host&quot;:null,&quot;loginBannerMessage&quot;:null,&quot;flash&quot;:null,&quot;can_create_user&quot;:true,&quot;stripePublishableKey&quot;:&quot;pk_ZPBtv9wYtkUh6YwhwKRqL0ygAb0Q9&quot;}" id="ec62bfa4-6436-41ba-8321-a86221c111ee" /><script type="text/javascript">var renderContext = JSON.parse(document.getElementById('ec62bfa4-6436-41ba-8321-a86221c111ee').content);</script><script async src="https://cdn.optimizely.com/js/14812510231.js" type="text/javascript"></script>
<script type="text/javascript">
!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t,e){var n=document.createElement("script");n.type="text/javascript";n.async=!0;n.src="https://cdn.sment.cm/analyts.js/v1/"+t+"/analytics.min.js";var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(n,a);analytics._loadOptions=e};analytics.SNIPPET_VERSION="4.1.0";
var optout = window.renderContext.current_user &&
  window.renderContext.current_user.privacy_optout;

if (optout) {
 analytics.load(segmentWriteKey, {
  integrations: {
   All: false,
   Amplitude: true,
   Postgres: true
  }
 });
} else {
 analytics.load(segmentWriteKey);
}
}}();
</script>

<script src="//d3dy5gmtp8yhk7.cloudfront.net/2.2/pusher.min.js" type="text/javascript"></script><meta content="{&quot;user&quot;:{&quot;email&quot;:null,&quot;name&quot;:null,&quot;key&quot;:&quot;&quot;,&quot;custom&quot;:{&quot;organizations&quot;:[],&quot;in_beta_program&quot;:null,&quot;enrolled_betas&quot;:null,&quot;free&quot;:true}},&quot;client-id&quot;:&quot;562fbc5f169cf106f1000015&quot;,&quot;flags&quot;:{&quot;update-zuora-billing-info&quot;:false,&quot;circle-11121-uncertified-orbs-allowed&quot;:true,&quot;disable-performance-signup&quot;:false,&quot;new-build-logs&quot;:false,&quot;force-redirect-to-new-ui&quot;:false,&quot;circle-6591-migrate-to-js-card&quot;:null,&quot;project-cache-clear-buttons&quot;:null,&quot;plan-overview-loading-override&quot;:false,&quot;project-set-up-march-2019&quot;:&quot;not-in-test&quot;,&quot;allow-interim-performance-chargify&quot;:false,&quot;show-active-users&quot;:true,&quot;org-usage-banners&quot;:true,&quot;circle-13360-gh-checks&quot;:true,&quot;free-check-in-execution-authorized&quot;:true,&quot;eol-banners&quot;:true,&quot;swap-authorized-event-names&quot;:true,&quot;job-page-sort-by-repo-name-alphabetically&quot;:false,&quot;orbs-enabled&quot;:true,&quot;pipelines-opt-in-banner&quot;:true,&quot;upgrade-alert-free-container-customers&quot;:true,&quot;js-component-alerts&quot;:false,&quot;plans-performance-overview&quot;:true,&quot;billing-zuora&quot;:null,&quot;upgrade-alert-paid-container-customers&quot;:true,&quot;plan-share-web-ui&quot;:true,&quot;open-pull-request&quot;:null,&quot;projects-page&quot;:null,&quot;github-student-pack&quot;:null,&quot;plan-usage-web-ui&quot;:true,&quot;import-env-vars&quot;:true,&quot;plans-performance-usage&quot;:true,&quot;audit&quot;:true,&quot;offer-linux-trial&quot;:null,&quot;setup-docs-ab-test&quot;:null,&quot;web-ui-job-detail-opt-in&quot;:true,&quot;insights-org-workflows-api&quot;:true,&quot;log-invalid-routes&quot;:false,&quot;plan-overview-web-ui&quot;:true,&quot;paid-usage-upgrade-banner&quot;:true,&quot;insights-direct-api-request-access&quot;:false,&quot;usage-credits&quot;:true,&quot;web-ui-auto-opt-in&quot;:true,&quot;enterprise-ui&quot;:null,&quot;job-page-rerun-workflow-from-failed&quot;:false}}" id="40727ad0-be6f-49e8-a6b9-0fb2931b5439" /><script type="text/javascript">var launchDarkly = JSON.parse(document.getElementById('40727ad0-be6f-49e8-a6b9-0fb2931b5439').content);</script><meta content="{&quot;accessToken&quot;:&quot;88e6275c49774d618916bfb4b4e13dfa&quot;,&quot;captureUncaught&quot;:true,&quot;captureUnhandledRejections&quot;:true,&quot;hostWhiteList&quot;:[&quot;dmmj3mmt94rvw.cloudfront.net&quot;,&quot;circleci.com&quot;],&quot;payload&quot;:{&quot;environment&quot;:&quot;production&quot;,&quot;client&quot;:{&quot;javascript&quot;:{&quot;code_version&quot;:&quot;3e3971eb5e8d270ec6e77c07b0a750a96324539a&quot;}}}}" id="948884a0-3bcd-45e1-87d8-9c20d5723a8d" /><script type="text/javascript">var _rollbarConfig = JSON.parse(document.getElementById('948884a0-3bcd-45e1-87d8-9c20d5723a8d').content);</script><script>!function(r){function o(n){if(e[n])return e[n].exports;var t=e[n]={exports:{},id:n,loaded:!1};return r[n].call(t.exports,t,t.exports,o),t.loaded=!0,t.exports}var e={};return o.m=r,o.c=e,o.p="",o(0)}([function(r,o,e){"use strict";var n=e(1),t=e(4);_rollbarConfig=_rollbarConfig||{},_rollbarConfig.rollbarJsUrl=_rollbarConfig.rollbarJsUrl||"https://dmmj3mmt94rvw.cloudfront.net/assets/js/hosted/rollbar-4fcef5ccc29985d4878f2e7c5676180b.min.js",_rollbarConfig.async=void 0===_rollbarConfig.async||_rollbarConfig.async;var a=n.setupShim(window,_rollbarConfig),l=t(_rollbarConfig);window.rollbar=n.Rollbar,a.loadFull(window,document,!_rollbarConfig.async,_rollbarConfig,l)},function(r,o,e){"use strict";function n(r){return function(){try{return r.apply(this,arguments)}catch(r){try{console.error("[Rollbar]: Internal error",r)}catch(r){}}}}function t(r,o){this.options=r,this._rollbarOldOnError=null;var e=s++;this.shimId=function(){return e},window&&window._rollbarShims&&(window._rollbarShims[e]={handler:o,messages:[]})}function a(r,o){var e=o.globalAlias||"Rollbar";if("object"==typeof r[e])return r[e];r._rollbarShims={},r._rollbarWrappedError=null;var t=new p(o);return n(function(){o.captureUncaught&&(t._rollbarOldOnError=r.onerror,i.captureUncaughtExceptions(r,t,!0),i.wrapGlobals(r,t,!0)),o.captureUnhandledRejections&&i.captureUnhandledRejections(r,t,!0);var n=o.autoInstrument;return(void 0===n||n===!0||"object"==typeof n&&n.network)&&r.addEventListener&&(r.addEventListener("load",t.captureLoad.bind(t)),r.addEventListener("DOMContentLoaded",t.captureDomContentLoaded.bind(t))),r[e]=t,t})()}function l(r){return n(function(){var o=this,e=Array.prototype.slice.call(arguments,0),n={shim:o,method:r,args:e,ts:new Date};window._rollbarShims[this.shimId()].messages.push(n)})}var i=e(2),s=0,d=e(3),c=function(r,o){return new t(r,o)},p=d.bind(null,c);t.prototype.loadFull=function(r,o,e,t,a){var l=function(){var o;if(void 0===r._rollbarDidLoad){o=new Error("rollbar.js did not load");for(var e,n,t,l,i=0;e=r._rollbarShims[i++];)for(e=e.messages||[];n=e.shift();)for(t=n.args||[],i=0;i<t.length;++i)if(l=t[i],"function"==typeof l){l(o);break}}"function"==typeof a&&a(o)},i=!1,s=o.createElement("script"),d=o.getElementsByTagName("script")[0],c=d.parentNode;s.crossOrigin="",s.src=t.rollbarJsUrl,e||(s.async=!0),s.onload=s.onreadystatechange=n(function(){if(!(i||this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState)){s.onload=s.onreadystatechange=null;try{c.removeChild(s)}catch(r){}i=!0,l()}}),c.insertBefore(s,d)},t.prototype.wrap=function(r,o,e){try{var n;if(n="function"==typeof o?o:function(){return o||{}},"function"!=typeof r)return r;if(r._isWrap)return r;if(!r._rollbar_wrapped&&(r._rollbar_wrapped=function(){e&&"function"==typeof e&&e.apply(this,arguments);try{return r.apply(this,arguments)}catch(e){var o=e;throw"string"==typeof o&&(o=new String(o)),o._rollbarContext=n()||{},o._rollbarContext._wrappedSource=r.toString(),window._rollbarWrappedError=o,o}},r._rollbar_wrapped._isWrap=!0,r.hasOwnProperty))for(var t in r)r.hasOwnProperty(t)&&(r._rollbar_wrapped[t]=r[t]);return r._rollbar_wrapped}catch(o){return r}};for(var u="log,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleUnhandledRejection,captureDomContentLoaded,captureLoad".split(","),f=0;f<u.length;++f)t.prototype[u[f]]=l(u[f]);r.exports={setupShim:a,Rollbar:p}},function(r,o){"use strict";function e(r,o,e){if(r){var t;"function"==typeof o._rollbarOldOnError?t=o._rollbarOldOnError:r.onerror&&!r.onerror.belongsToShim&&(t=r.onerror,o._rollbarOldOnError=t);var a=function(){var e=Array.prototype.slice.call(arguments,0);n(r,o,t,e)};a.belongsToShim=e,r.onerror=a}}function n(r,o,e,n){r._rollbarWrappedError&&(n[4]||(n[4]=r._rollbarWrappedError),n[5]||(n[5]=r._rollbarWrappedError._rollbarContext),r._rollbarWrappedError=null),o.handleUncaughtException.apply(o,n),e&&e.apply(r,n)}function t(r,o,e){if(r){"function"==typeof r._rollbarURH&&r._rollbarURH.belongsToShim&&r.removeEventListener("unhandledrejection",r._rollbarURH);var n=function(r){var e=r.reason,n=r.promise,t=r.detail;!e&&t&&(e=t.reason,n=t.promise),o&&o.handleUnhandledRejection&&o.handleUnhandledRejection(e,n)};n.belongsToShim=e,r._rollbarURH=n,r.addEventListener("unhandledrejection",n)}}function a(r,o,e){if(r){var n,t,a="EventTarget,Window,Node,ApplicationCache,AudioTrackList,ChannelMergerNode,CryptoOperation,EventSource,FileReader,HTMLUnknownElement,IDBDatabase,IDBRequest,IDBTransaction,KeyOperation,MediaController,MessagePort,ModalWindow,Notification,SVGElementInstance,Screen,TextTrack,TextTrackCue,TextTrackList,WebSocket,WebSocketWorker,Worker,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload".split(",");for(n=0;n<a.length;++n)t=a[n],r[t]&&r[t].prototype&&l(o,r[t].prototype,e)}}function l(r,o,e){if(o.hasOwnProperty&&o.hasOwnProperty("addEventListener")){for(var n=o.addEventListener;n._rollbarOldAdd&&n.belongsToShim;)n=n._rollbarOldAdd;var t=function(o,e,t){n.call(this,o,r.wrap(e),t)};t._rollbarOldAdd=n,t.belongsToShim=e,o.addEventListener=t;for(var a=o.removeEventListener;a._rollbarOldRemove&&a.belongsToShim;)a=a._rollbarOldRemove;var l=function(r,o,e){a.call(this,r,o&&o._rollbar_wrapped||o,e)};l._rollbarOldRemove=a,l.belongsToShim=e,o.removeEventListener=l}}r.exports={captureUncaughtExceptions:e,captureUnhandledRejections:t,wrapGlobals:a}},function(r,o){"use strict";function e(r,o){this.impl=r(o,this),this.options=o,n(e.prototype)}function n(r){for(var o=function(r){return function(){var o=Array.prototype.slice.call(arguments,0);if(this.impl[r])return this.impl[r].apply(this.impl,o)}},e="log,debug,info,warn,warning,error,critical,global,configure,handleUncaughtException,handleUnhandledRejection,_createItem,wrap,loadFull,shimId,captureDomContentLoaded,captureLoad".split(","),n=0;n<e.length;n++)r[e[n]]=o(e[n])}e.prototype._swapAndProcessMessages=function(r,o){this.impl=r(this.options);for(var e,n,t;e=o.shift();)n=e.method,t=e.args,this[n]&&"function"==typeof this[n]&&("captureDomContentLoaded"===n||"captureLoad"===n?this[n].apply(this,[t[0],e.ts]):this[n].apply(this,t));return this},r.exports=e},function(r,o){"use strict";r.exports=function(r){return function(o){if(!o&&!window._rollbarInitialized){r=r||{};for(var e,n,t=r.globalAlias||"Rollbar",a=window.rollbar,l=function(r){return new a(r)},i=0;e=window._rollbarShims[i++];)n||(n=e.handler),e.handler._swapAndProcessMessages(l,e.messages);window[t]=n,window._rollbarInitialized=!0}}}}]);
</script></head><noscript><h1>Hello there noscripter!</h1><p>CircleCI uses JavaScript pretty heavily to provide a good experience and to allow us to develop code a lot faster. We recognize that the tradeoff is that people using noscript get a worse experience, and we apologize for that.</p><p>So let us pitch you quickly on why you should enable JavaScript and view our site. CircleCI is <b>powerful, fast, and easy-to-use Continuous Integration and Deployment</b> for web applications.</p><p>CircleCI is easy to set up, incredibly fast, allows you to get your code to customers faster, and will even automatically parallelize your tests over many machines to get results to you faster. If that sounds useful, we'd encourage you to whitelist us in noscript and read about it yourself :)</p></noscript><body><div id="app"></div><script crossorigin="anonymous" src="https://dmmj3mmt94rvw.cloudfront.net/assets/js/frontend-production-5ab8a5e94b7618dc5c0e4a9a98e2afcb.js" type="text/javascript"></script>
<script id="ze-snippet" async src="https://static.zdaets.com/ekr/snippet.js?key=d6a46f2f-d5c089096bfe3"> </script>

The job step is to run terraform plan

Hi @barywhyte !

Based on the output, I believe the issue is the URL is incorrect, that response is basically what is returned if you aren’t hitting a valid endpoint.

For the above, that leads me to believe the API_URL variable is either not being set, or set incorrectly. Can you confirm that before trying the curl you are setting that value with:

API_URL=$(echo $CIRCLE_BUILD_URL | cut -d/ -f4-7)

If so, then I think I may need to troubleshoot further by viewing the build in question. You can either provide a link to that here, or if you prefer, open a support ticket and reference this post and mention my name in it and I’ll grab the case and take a look.

Hi @nbialostosky
This is my api_url from echo $API_URL command
gh/$ORG_NAME/$PROJECT_NAME/3338

$ORG_NAME = my organization name on CircleCI
$PROJECT_NAME = my project name CircleCI

That looks correct then, so it should be working. I re-tested the commands listed in this article on one of my projects and it worked as expected. I think at this point i’ll need to look at a failing build link to see if I can get some additional details. Alternatively, if you want to still dig into it further yourself you could re-run the job with SSH and then try executing the commands directly/verify all the variables are set correctly.

@nbialostosky

I have some hope since this still works for you but I don’t know what I am doing wrong here.
I actually logged into the container via ssh like you mentioned above. I tried these steps one after the other and this is the part where things began to break down:

FAILED_STEP=$(curl "https://circleci.com/api/v1.1/$PROJECT_NAME/${API_URL}?circle-token=${CIRCLECI_API_TOKEN}" | jq '.steps | .[] | flatten | map(select(.status? == "failed")) | .[] | {allocation_id, step}')

As I echo $FAILED_STEP, the output is empty.

I think I will be very fortunate to have you help me dig into this build

Hi @barywhyte ,

Sounds good – my first guess is that if your step you are trying to output isn’t failing, then that may be why the output is blank as the jq is filtering and looking for a failed step.

With the above said, if you do submit a ticket with a build link for me to look at, I can take a closer look.

Thanks!

Hello @nbialostosky

Thank you very much. Yea you are right! I deliberately setup a step to fail so I can get a sense of how this looks like in slack channel. How can I raise a ticket?

Thank you!

@barywhyte you can submit one here:

https://support.circleci.com/hc/en-us/requests/new

Or you can email support@circleci.com – both should generate a ticket.

Thank you! I hope this get assigned to you :slight_smile:

Thank you @nbialostosky I have raised a ticket for this

1 Like