Skip to content

Migrate from CircleCI to GitHub Actions #1351

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 15 additions & 62 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,75 +1,28 @@
---
# CI has been migrated to GitHub Actions
# Keeping this file so that previous pull requests continue working
# This file does not generate any CircleCI workflow

version: 2.1
orbs:
prometheus: prometheus/[email protected]
executors:
# Whenever the Go version is updated here, .promu.yml should also be updated.
golang:
docker:
- image: cimg/go:1.23
- image: busybox
jobs:
test:
noopjob:
executor: golang
steps:
- prometheus/setup_environment
- run: make
- prometheus/store_artifact:
file: blackbox_exporter
- run: git diff --exit-code
# IPv6 tests require the machine executor.
# See https://circleci.com/docs/2.0/faq/#can-i-use-ipv6-in-my-tests for details.
test-ipv6:
machine: true
working_directory: /home/circleci/.go_workspace/src/github.com/prometheus/blackbox_exporter
# Whenever the Go version is updated here, .promu.yml should also be updated.
environment:
DOCKER_TEST_IMAGE_NAME: quay.io/prometheus/golang-builder:1.23-base
steps:
- checkout
- run:
name: enable ipv6
command: |
cat \<<'EOF' | sudo tee /etc/docker/daemon.json
{
"ipv6": true,
"fixed-cidr-v6": "2001:db8:1::/64"
}
EOF
sudo service docker restart
- run: docker run --rm -t -v "$(pwd):/app" "${DOCKER_TEST_IMAGE_NAME}" -i github.com/prometheus/blackbox_exporter -T
command: "true"
workflows:
version: 2
blackbox_exporter:
prometheus:
jobs:
- test:
filters:
tags:
only: /.*/
- test-ipv6:
filters:
tags:
only: /.*/
- prometheus/build:
name: build
filters:
tags:
only: /.*/
- prometheus/publish_master:
context: org-context
requires:
- test
- test-ipv6
- build
filters:
branches:
only: master
- prometheus/publish_release:
context: org-context
requires:
- test
- test-ipv6
- build
- noopjob
triggers:
- schedule:
cron: "0 0 30 2 *"
filters:
tags:
only: /^v[0-9]+(\.[0-9]+){2}(-.+|[^-.]*)$/
branches:
ignore: /.*/
only:
- master
109 changes: 109 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
name: CI
on:
- push
- pull_request
jobs:
test:
name: Test
strategy:
matrix:
os:
- ubuntu-24.04
- windows-2022
- macos-13
- macos-14
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/[email protected]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be pinned to commit hash for supply chain security.

Suggested change
uses: actions/[email protected]
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Read .promu.yml
uses: pietrobolcato/action-read-yaml@dd664040f4883322f6d143e58302062b35a46e4d
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if possible, we would like to avoid using third party actions, and would prefer to only use actions from actions and prometheus orgs.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not see any actions from actions or prometheus that would allow this.

Prometheus kindly asks and hopes that people remember to update the .promu.yml to match the Go version:

https://github.com/prometheus/prometheus/blob/02501e097e3ed31cb34ec7a42963d41718c90010/.github/workflows/ci.yml#L12C7-L14C57

This seems more flimsy to me than directly pointing to a specific commit of a third-party that can just pull the go version from the .promu.yml file for us.

If you disagree, I can add a comment similar to Prometheus and hardcode the Go version, just thought this was better in my opinion.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like do this the way Prometheus does for consistency across repos in Prometheus org, we already have a similar comment for circleci.

# Whenever the Go version is updated here, .circle/config.yml should also be updated.

id: read_promu
with:
config: .promu.yml
- name: Set up Go
uses: actions/[email protected]
with:
go-version: ${{ steps.read_promu.outputs['go.version'] }}
- run: make build
- run: make test GOOPTS=-v

build_common:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reasons to split the build into build_common and build steps?

Copy link
Author

@bryce-souers bryce-souers Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea was to build "common" architectures when someone submits a PR so reviewers can download the binary and test things quickly.

This was inspired from Prometheus's implementation where they appear to do the same thing:

https://github.com/prometheus/prometheus/blob/02501e097e3ed31cb34ec7a42963d41718c90010/.github/workflows/ci.yml#L109C1-L119C78

Then when there is a release or merge to main, all the architectures are built.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I okay with the split, but let's add this info as a comment as also link to Prometheus so we document the reason on why why we split the build.

name: Build common architectures
if: github.event_name == 'pull_request'
strategy:
matrix:
thread: [0, 1, 2]
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/[email protected]
- name: Import PromCI
uses: prometheus/[email protected]
- name: Cross-build
uses: ./.github/promci/actions/build
with:
thread: ${{ matrix.thread }}
parallelism: 3
promu_opts: -p linux/amd64 -p windows/amd64 -p linux/arm64 -p darwin/amd64 -p darwin/arm64 -p linux/386

build_all:
name: Build all architectures
if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v0.'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, this will also break with v1.x.x release

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous response.

strategy:
matrix:
thread: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/[email protected]
- name: Import PromCI
uses: prometheus/[email protected]
- name: Cross-build
uses: ./.github/promci/actions/build
with:
thread: ${{ matrix.thread }}
parallelism: 12
promu_opts: -p linux

publish_master:
name: Publish master
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
needs:
- test
- build_all
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/[email protected]
- name: Import PromCI
uses: prometheus/[email protected]
- name: Publish
uses: ./.github/promci/actions/publish_main
with:
docker_hub_login: ${{ secrets.DOCKER_HUB_LOGIN }}
docker_hub_password: ${{ secrets.DOCKER_HUB_PASSWORD }}
quay_io_login: ${{ secrets.QUAY_IO_LOGIN }}
quay_io_password: ${{ secrets.QUAY_IO_PASSWORD }}

publish_release:
name: Publish release
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v0.')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will break when we go to 1.x.x release

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@electron0zero
Is it enough to add an OR where we also check if the tag starts with "v1." too?

Unfortunately, regex is not a part of the functions in GitHub Actions so we are stuck with checking the start, which is why I assume that Prometheus also does this using this method:

https://github.com/prometheus/prometheus/blob/02501e097e3ed31cb34ec7a42963d41718c90010/.github/workflows/ci.yml#L224C7-L226C79

It seems like it would be very hacky to try to work around this limitation of Actions to avoid a problem that is very easy to solve (just adding the relevant version prefix).

needs:
- test
- build_all
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/[email protected]
- name: Import PromCI
uses: prometheus/[email protected]
- name: Publish
uses: ./.github/promci/actions/publish_release
with:
github_token: ${{ secrets.PROMBOT_GITHUB_TOKEN }}
docker_hub_login: ${{ secrets.DOCKER_HUB_LOGIN }}
docker_hub_password: ${{ secrets.DOCKER_HUB_PASSWORD }}
quay_io_login: ${{ secrets.QUAY_IO_LOGIN }}
quay_io_password: ${{ secrets.QUAY_IO_PASSWORD }}
25 changes: 12 additions & 13 deletions .promu.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
go:
# Whenever the Go version is updated here, .circle/config.yml should also be updated.
version: 1.23
version: 1.23
repository:
path: github.com/prometheus/blackbox_exporter
path: github.com/prometheus/blackbox_exporter
build:
ldflags: |
-X github.com/prometheus/common/version.Version={{.Version}}
-X github.com/prometheus/common/version.Revision={{.Revision}}
-X github.com/prometheus/common/version.Branch={{.Branch}}
-X github.com/prometheus/common/version.BuildUser={{user}}@{{host}}
-X github.com/prometheus/common/version.BuildDate={{date "20060102-15:04:05"}}
ldflags: |
-X github.com/prometheus/common/version.Version={{.Version}}
-X github.com/prometheus/common/version.Revision={{.Revision}}
-X github.com/prometheus/common/version.Branch={{.Branch}}
-X github.com/prometheus/common/version.BuildUser={{user}}@{{host}}
-X github.com/prometheus/common/version.BuildDate={{date "20060102-15:04:05"}}
tarball:
files:
- blackbox.yml
- LICENSE
- NOTICE
files:
- blackbox.yml
- LICENSE
- NOTICE
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Blackbox exporter

[![CircleCI](https://circleci.com/gh/prometheus/blackbox_exporter/tree/master.svg?style=shield)][circleci]
[![CI](https://github.com/prometheus/blackbox_exporter/actions/workflows/ci.yml/badge.svg)](https://github.com/prometheus/blackbox_exporter/actions/workflows/ci.yml)
[![Docker Repository on Quay](https://quay.io/repository/prometheus/blackbox-exporter/status)][quay]
[![Docker Pulls](https://img.shields.io/docker/pulls/prom/blackbox-exporter.svg?maxAge=604800)][hub]

Expand Down Expand Up @@ -159,6 +159,5 @@ The ICMP probe requires elevated privileges to function:
* *BSD*: root user is required.
* *OS X*: No additional privileges are needed.

[circleci]: https://circleci.com/gh/prometheus/blackbox_exporter
[hub]: https://hub.docker.com/r/prom/blackbox-exporter/
[quay]: https://quay.io/repository/prometheus/blackbox-exporter
17 changes: 0 additions & 17 deletions prober/dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package prober
import (
"context"
"net"
"os"
"runtime"
"testing"
"time"
Expand Down Expand Up @@ -90,10 +89,6 @@ func recursiveDNSHandler(w dns.ResponseWriter, r *dns.Msg) {
}

func TestRecursiveDNSResponse(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

tests := []struct {
Probe config.DNSProbe
ShouldSucceed bool
Expand Down Expand Up @@ -247,10 +242,6 @@ func authoritativeDNSHandler(w dns.ResponseWriter, r *dns.Msg) {
}

func TestAuthoritativeDNSResponse(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

tests := []struct {
Probe config.DNSProbe
ShouldSucceed bool
Expand Down Expand Up @@ -398,10 +389,6 @@ func TestAuthoritativeDNSResponse(t *testing.T) {
}

func TestServfailDNSResponse(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

tests := []struct {
Probe config.DNSProbe
ShouldSucceed bool
Expand Down Expand Up @@ -475,10 +462,6 @@ func TestServfailDNSResponse(t *testing.T) {
}

func TestDNSProtocol(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

// This test assumes that listening TCP listens both IPv6 and IPv4 traffic and
// localhost resolves to both 127.0.0.1 and ::1. we must skip the test if either
// of these isn't true. This should be true for modern Linux systems.
Expand Down
24 changes: 0 additions & 24 deletions prober/grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ import (
)

func TestGRPCConnection(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

ln, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("Error listening on socket: %s", err)
Expand Down Expand Up @@ -103,10 +99,6 @@ func TestGRPCConnection(t *testing.T) {
}

func TestMultipleGRPCservices(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

ln, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("Error listening on socket: %s", err)
Expand Down Expand Up @@ -172,10 +164,6 @@ func TestMultipleGRPCservices(t *testing.T) {
}

func TestGRPCTLSConnection(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

certExpiry := time.Now().AddDate(0, 0, 1)
testCertTmpl := generateCertificateTemplate(certExpiry, false)
testCertTmpl.IsCA = true
Expand Down Expand Up @@ -267,10 +255,6 @@ func TestGRPCTLSConnection(t *testing.T) {
}

func TestNoTLSConnection(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

ln, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("Error listening on socket: %s", err)
Expand Down Expand Up @@ -325,10 +309,6 @@ func TestNoTLSConnection(t *testing.T) {
}

func TestGRPCServiceNotFound(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

ln, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("Error listening on socket: %s", err)
Expand Down Expand Up @@ -381,10 +361,6 @@ func TestGRPCServiceNotFound(t *testing.T) {
}

func TestGRPCHealthCheckUnimplemented(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

ln, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("Error listening on socket: %s", err)
Expand Down
12 changes: 0 additions & 12 deletions prober/tcp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,6 @@ func TestTCPConnectionFails(t *testing.T) {
}

func TestTCPConnectionWithTLS(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

ln, err := net.Listen("tcp", ":0")
if err != nil {
t.Fatalf("Error listening on socket: %s", err)
Expand Down Expand Up @@ -201,10 +197,6 @@ func TestTCPConnectionWithTLS(t *testing.T) {
}

func TestTCPConnectionWithTLSAndVerifiedCertificateChain(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("Error listening on socket: %s", err)
Expand Down Expand Up @@ -581,10 +573,6 @@ func TestTCPConnectionQueryResponseMatching(t *testing.T) {
}

func TestTCPConnectionProtocol(t *testing.T) {
if os.Getenv("CI") == "true" {
t.Skip("skipping; CI is failing on ipv6 dns requests")
}

// This test assumes that listening TCP listens both IPv6 and IPv4 traffic and
// localhost resolves to both 127.0.0.1 and ::1. we must skip the test if either
// of these isn't true. This should be true for modern Linux systems.
Expand Down
Loading
Loading