Skip to content

Commit

Permalink
Merge pull request #234 from collectiveidea/circle-webhook-upgrade
Browse files Browse the repository at this point in the history
Circle CI Webhook Upgrade
  • Loading branch information
danielmorrison authored Jan 10, 2024
2 parents 3287ff4 + 822e997 commit be23d35
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 80 deletions.
3 changes: 0 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,3 @@ jobs:
command: yarn build:css
- run:
command: bundle exec rake
notify:
webhooks:
- url: https://buildlight.collectiveidea.com
8 changes: 1 addition & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,7 @@ notifications:

### Circle CI

Simply add this to your `.circle/config.yml` file:

```
notify:
webhooks:
- url: https://buildlight.collectiveidea.com
```
Go to your project settings in Circle CI and add a new Webhook with `https://buildlight.collectiveidea.com` as the Receiver URL. Ensure the the "Workflow Completed" event is checked.

## Viewing Status

Expand Down
4 changes: 2 additions & 2 deletions app/controllers/webhooks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ def create
elsif params[:payload].blank? && params[:repository]&.include?("/")
ParseGithub.call(params)
head :ok && return
elsif params[:payload]
ParseCircle.call(params[:payload])
elsif request.headers.env["HTTP_CIRCLECI_EVENT_TYPE"].present?
ParseCircle.call(params)
head :ok && return
end

Expand Down
25 changes: 10 additions & 15 deletions app/interactors/parse_circle.rb
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
class ParseCircle
def self.call(payload)
return unless payload["pull_requests"].blank?
return unless payload["type"] == "workflow-completed"
# Ignore pull requests. We can't really determine a PR build, so we ignore any branches other than main/master.
return unless payload.dig("pipeline", "vcs", "branch").in? ["main", "master"]

status = Status.find_or_initialize_by(service: "circle", username: payload["username"], project_name: payload["reponame"])
status = Status.find_or_initialize_by(service: "circle", username: payload["organization"]["name"], project_name: payload["project"]["name"])
status.payload = payload if Rails.configuration.x.debug
set_colors(status, payload["status"])
set_colors(status, payload["workflow"]["status"])
status.save!
end

# Options
# :retried, :canceled, :infrastructure_fail, :timedout, :not_run, :running,
# :failed, :queued, :scheduled, :not_running, :no_tests, :fixed, :success
# Potential Statuses
# See: https://circleci.com/docs/webhooks/#event-specifications
# "success", "failed", "error", "canceled", "unauthorized"
def self.set_colors(status, code)
status.yellow = false
case code
when "running", "queued", "scheduled"
status.yellow = true
when "success", "fixed"
status.red = false
else
status.red = true
end
status.yellow = false # currently no way to set yellow on Circle
status.red = code != "success"
end
end
32 changes: 0 additions & 32 deletions spec/controllers/webhooks_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,38 +46,6 @@
end
end

describe "from Circle CI" do
it "recieves a json payload" do
post :create, params: JSON.parse(json_fixture("circle.json"))
expect(response).to be_successful
end

it "saves useful data" do
post :create, params: JSON.parse(json_fixture("circle.json"))
status = Status.order("created_at DESC").first
expect(status.red).to be(false)
expect(status.service).to eq("circle")
expect(status.project_id).to be_nil
expect(status.project_name).to eq("buildlight")
expect(status.username).to eq("collectiveidea")
end

it "ignores pull requests" do
expect(Status.count).to eq(0)
data = JSON.parse(json_fixture("circle_pr.json"))
data["payload"]["pull_requests"] = [{not: "empty"}]
post :create, params: data
expect(Status.count).to eq(0)
end

it "notifies Particle" do
FactoryBot.create(:device, :with_identifier, usernames: ["collectiveidea"])
allow(Particle).to receive(:publish)
post :create, params: JSON.parse(json_fixture("circle.json"))
expect(Particle).to have_received(:publish).with(name: "build_state", data: "passing", ttl: 3600, private: false)
end
end

describe "from GitHub Actions" do
it "recieves a json payload" do
post :create, params: JSON.parse(json_fixture("github.json"))
Expand Down
2 changes: 1 addition & 1 deletion spec/fixtures/circle.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion spec/fixtures/circle_pr.json

Large diffs are not rendered by default.

21 changes: 2 additions & 19 deletions spec/interactors/parse_circle_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,10 @@
expect(@status.yellow).to be(false)
end

it "sets fixed to green" do
ParseCircle.set_colors(@status, "fixed")
expect(@status.red).to be(false)
expect(@status.yellow).to be(false)
end

it "sets timedout to red" do
ParseCircle.set_colors(@status, "timedout")
it "sets failed to red" do
ParseCircle.set_colors(@status, "failed")
expect(@status.red).to be(true)
expect(@status.yellow).to be(false)
end

it "sets running to yellow" do
ParseCircle.set_colors(@status, "running")
expect(@status.yellow).to be(true)
end

it "keeps the red color if yellow" do
@status.red = true
ParseCircle.set_colors(@status, "running")
expect(@status.red).to be(true)
end
end
end
35 changes: 35 additions & 0 deletions spec/requests/circle_webhooks_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require "rails_helper"

describe "Webhooks from Circle CI" do
before do
allow(Particle).to receive(:publish)
end

it "recieves a json payload" do
post "/", params: json_fixture("circle.json"), headers: {"content-type": "application/json", "Circleci-Event-Type": "workflow-completed"}
expect(response).to be_successful
end

it "saves useful data" do
post "/", params: json_fixture("circle.json"), headers: {"content-type": "application/json", "Circleci-Event-Type": "workflow-completed"}
status = Status.order("created_at DESC").first
expect(status.red).to be(false)
expect(status.service).to eq("circle")
expect(status.project_id).to be_nil
expect(status.project_name).to eq("buildlight")
expect(status.username).to eq("collectiveidea")
end

it "ignores pull requests" do
expect(Status.count).to eq(0)
post "/", params: json_fixture("circle_pr.json"), headers: {"content-type": "application/json", "Circleci-Event-Type": "workflow-completed"}
expect(Status.count).to eq(0)
end

it "notifies Particle" do
FactoryBot.create(:device, :with_identifier, usernames: ["collectiveidea"])
allow(Particle).to receive(:publish)
post "/", params: json_fixture("circle.json"), headers: {"content-type": "application/json", "Circleci-Event-Type": "workflow-completed"}
expect(Particle).to have_received(:publish).with(name: "build_state", data: "passing", ttl: 3600, private: false)
end
end

0 comments on commit be23d35

Please sign in to comment.