Repository: skupperproject/skupper
Pull request #1288 (2023-11-21 18:03:22)

Disable CGO for CI Builds
Currently releases contain a linux/amd64 skupper-cli asset built with CGO, the default behavior for the go toolchain for native builds. The consequence of this is a less portable executable. This change disables CGO for our tests and builds in CircleCI, and will produce statically linked pure go executables for all platforms uniformly.

nluaces: Thanks @c-kruse ! I think we need the build to run to see if there is any issue 🤔 ...Hey @fgiorgetti do you think that the build is not running because Christian is not included yet in the `skupper-org` in the CI?
fgiorgetti: > Thanks @c-kruse ! I think we need the build to run to see if there is any issue 🤔 ...Hey @fgiorgetti do you think that the build is not running because Christian is not included yet in the `skupper-org` in the CI?

@nluaces I remember that it won't build if user has set up his fork to run in CircleCI.

@c-kruse The following doc, explains the issue:
https://circleci.com/docs/oss/#build-pull-requests-from-forked-repositories

`If a user submits a pull request to your repository from a fork, but no pipeline is triggered, then the user most likely is following a project fork on their personal account rather than the project itself of CircleCI, causing the jobs to trigger under the user’s personal account and not the organization account. To resolve this issue, have the user unfollow their fork of the project on CircleCI and instead follow the source project. This will trigger their jobs to run under the organization when they submit pull requests.
`

If that is the case, you need to "Unfollow" your local fork on CircleCI.
I believe if you go to: https://app.circleci.com/pipelines/github/c-kruse/skupper and 
see that there are builds showing up, you have to click the "Project Settings" button, then "Unfollow Project".

Let me know if that helps.
c-kruse: Thank you @nluaces  and @fgiorgetti! That was it.

Also including an audit step in build-all for lack of better idea. To fully test this change we'd need to trigger a release to get the build artifacts and see all of the jobs run with the adjusted executor. At least with the audit step we can check that the linux/amd64 will turn out the way I intend (statically linked, CGO_ENABLED = 0).


Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 2e175afd..61b8b59f 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -5,6 +5,12 @@ orbs:
     go: circleci/go@1.7.1
 
 executors:
+  go_cimg:
+    docker:
+      - image: cimg/go:1.20
+    environment:
+      CGO_ENABLED: 0
+
   local_cluster_test_executor:
     machine:
       image: ubuntu-2204:2022.10.2
@@ -292,6 +298,12 @@ commands:
             go build -ldflags "-X github.com/skupperproject/skupper/pkg/version.Version=${VERSION}"
             -o dist/<< parameters.platform >>/skupper<< parameters.exesuffix >>
             ./cmd/skupper
+      - run:
+          name: Audit << parameters.platform >>
+          command: >-
+            sha512sum dist/<< parameters.platform >>/skupper<< parameters.exesuffix >>;
+            file dist/<< parameters.platform >>/skupper<< parameters.exesuffix >>;
+            go version -m dist/<< parameters.platform >>/skupper<< parameters.exesuffix >>;
 
   podman-latest:
     description: "Install latest podman v4 or higher"
@@ -411,8 +423,7 @@ workflows:
 jobs:
   test:
     executor:
-      name: go/default
-      tag: "1.20"
+      name: go_cimg
     steps:
       - checkout
       - run:
@@ -467,8 +478,7 @@ jobs:
 
   build-all:
     executor:
-      name: go/default
-      tag: "1.20"
+      name: go_cimg
     steps:
       - checkout
       - go/mod-download-cached
@@ -551,8 +561,7 @@ jobs:
 
   generate-manifest:
     executor:
-      name: go/default
-      tag: "1.20"
+      name: go_cimg
     steps:
       - checkout
       - go/mod-download-cached
@@ -591,8 +600,7 @@ jobs:
 
   publish-github-release-images:
     executor:
-      name: go/default
-      tag: "1.20"
+      name: go_cimg
     steps:
       - checkout
       - setup_remote_docker
@@ -612,8 +620,7 @@ jobs:
 
   publish-github-main-images:
     executor:
-      name: go/default
-      tag: "1.20"
+      name: go_cimg
     steps:
       - checkout
       - setup_remote_docker
diff --git a/pkg/flow/controller.go b/pkg/flow/controller.go
index 47978e0f..f7dde8f3 100644
--- a/pkg/flow/controller.go
+++ b/pkg/flow/controller.go
@@ -99,16 +99,13 @@ func UpdateHost(c *FlowController, deleted bool, name string, host *HostRecord)
 	return nil
 }
 
-func (c *FlowController) updateBeaconAndHeartbeats(stopCh <-chan struct{}) {
+func (c *FlowController) updateBeacon(stopCh <-chan struct{}) {
 	tickerAge := time.NewTicker(10 * time.Minute)
 	defer tickerAge.Stop()
 
 	beaconTimer := time.NewTicker(10 * time.Second)
 	defer beaconTimer.Stop()
 
-	heartbeatTimer := time.NewTicker(2 * time.Second)
-	defer heartbeatTimer.Stop()
-
 	identity := c.origin
 
 	beacon := &BeaconRecord{
@@ -119,20 +116,38 @@ func (c *FlowController) updateBeaconAndHeartbeats(stopCh <-chan struct{}) {
 		Identity:   identity,
 	}
 
+	c.beaconOutgoing <- beacon
+
+	for {
+		select {
+		case <-beaconTimer.C:
+			c.beaconOutgoing <- beacon
+		case <-tickerAge.C:
+		case <-stopCh:
+			return
+
+		}
+	}
+}
+
+func (c *FlowController) updateHeartbeats(stopCh <-chan struct{}) {
+	tickerAge := time.NewTicker(10 * time.Minute)
+	defer tickerAge.Stop()
+
+	heartbeatTimer := time.NewTicker(2 * time.Second)
+	defer heartbeatTimer.Stop()
+
 	heartbeat := &HeartbeatRecord{
 		Version:  1,
 		Identity: os.Getenv("SKUPPER_SITE_ID"),
 		Source:   "sfe." + c.origin,
 	}
 
-	c.beaconOutgoing <- beacon
 	heartbeat.Now = uint64(time.Now().UnixNano()) / uint64(time.Microsecond)
 	c.heartbeatOutgoing <- heartbeat
 
 	for {
 		select {
-		case <-beaconTimer.C:
-			c.beaconOutgoing <- beacon
 		case <-heartbeatTimer.C:
 			heartbeat.Now = uint64(time.Now().UnixNano()) / uint64(time.Microsecond)
 			c.heartbeatOutgoing <- heartbeat
@@ -223,12 +238,13 @@ func (c *FlowController) run(stopCh <-chan struct{}) {
 	recordSender.start()
 	flushReceiver.start()
 
-	go c.updateBeaconAndHeartbeats(stopCh)
+	go c.updateBeacon(stopCh)
+	go c.updateHeartbeats(stopCh)
 	go c.updateRecords(stopCh)
 	<-stopCh
 
 	beaconSender.stop()
-	heartbeatSender.start()
+	heartbeatSender.stop()
 	recordSender.stop()
 	flushReceiver.stop()
 }


Test patch:
diff --git a/pkg/flow/controller_test.go b/pkg/flow/controller_test.go
index f0badd1e..19dd9c88 100644
--- a/pkg/flow/controller_test.go
+++ b/pkg/flow/controller_test.go
@@ -64,7 +64,8 @@ func TestUpdateBeaconAndHeartbeats(t *testing.T) {
 	fc := NewFlowController("mySite", "X.Y.Z", uint64(time.Now().UnixNano())/uint64(time.Microsecond), nil)
 	assert.Assert(t, fc != nil)
 	stopCh := make(chan struct{})
-	go fc.updateBeaconAndHeartbeats(stopCh)
+	go fc.updateBeacon(stopCh)
+	go fc.updateHeartbeats(stopCh)
 	beaconUpdate := <-fc.beaconOutgoing
 	assert.Assert(t, beaconUpdate != nil)
 	beacon, ok := beaconUpdate.(*BeaconRecord)