Skip to content

Commit 1526164

Browse files
authored
Merge branch 'main' into kacpersaw/extend-build-reason
2 parents 2b5c4f2 + e4d3453 commit 1526164

File tree

129 files changed

+7851
-847
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+7851
-847
lines changed

.github/workflows/ci.yaml

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -451,16 +451,21 @@ jobs:
451451
# Postgres tends not to choke.
452452
NUM_PARALLEL_PACKAGES=8
453453
NUM_PARALLEL_TESTS=16
454+
# Only the CLI and Agent are officially supported on Windows and the rest are too flaky
455+
PACKAGES="./cli/... ./enterprise/cli/... ./agent/..."
454456
elif [ "${{ runner.os }}" == "macOS" ]; then
455457
# Our macOS runners have 8 cores. We set NUM_PARALLEL_TESTS to 16
456458
# because the tests complete faster and Postgres doesn't choke. It seems
457459
# that macOS's tmpfs is faster than the one on Windows.
458460
NUM_PARALLEL_PACKAGES=8
459461
NUM_PARALLEL_TESTS=16
462+
# Only the CLI and Agent are officially supported on macOS and the rest are too flaky
463+
PACKAGES="./cli/... ./enterprise/cli/... ./agent/..."
460464
elif [ "${{ runner.os }}" == "Linux" ]; then
461465
# Our Linux runners have 8 cores.
462466
NUM_PARALLEL_PACKAGES=8
463467
NUM_PARALLEL_TESTS=8
468+
PACKAGES="./..."
464469
fi
465470
466471
# by default, run tests with cache
@@ -477,10 +482,7 @@ jobs:
477482
# invalidated. See scripts/normalize_path.sh for more details.
478483
normalize_path_with_symlinks "$RUNNER_TEMP/sym" "$(dirname $(which terraform))"
479484
480-
# We rerun failing tests to counteract flakiness coming from Postgres
481-
# choking on macOS and Windows sometimes.
482-
gotestsum --rerun-fails=2 --rerun-fails-max-failures=50 \
483-
--format standard-quiet --packages "./..." \
485+
gotestsum --format standard-quiet --packages "$PACKAGES" \
484486
-- -timeout=20m -v -p $NUM_PARALLEL_PACKAGES -parallel=$NUM_PARALLEL_TESTS $TESTCOUNT
485487
486488
- name: Upload Go Build Cache
@@ -550,7 +552,6 @@ jobs:
550552
env:
551553
POSTGRES_VERSION: "17"
552554
TS_DEBUG_DISCO: "true"
553-
TEST_RETRIES: 2
554555
run: |
555556
make test-postgres
556557
@@ -604,7 +605,7 @@ jobs:
604605
POSTGRES_VERSION: "17"
605606
run: |
606607
make test-postgres-docker
607-
gotestsum --junitfile="gotests.xml" --packages="./..." --rerun-fails=2 --rerun-fails-abort-on-data-race -- -race -parallel 4 -p 4
608+
gotestsum --junitfile="gotests.xml" --packages="./..." -- -race -parallel 4 -p 4
608609
609610
- name: Upload Test Cache
610611
uses: ./.github/actions/test-cache/upload
@@ -726,7 +727,6 @@ jobs:
726727
if: ${{ !matrix.variant.premium }}
727728
env:
728729
DEBUG: pw:api
729-
CODER_E2E_TEST_RETRIES: 2
730730
working-directory: site
731731

732732
# Run all of the tests with a premium license
@@ -736,7 +736,6 @@ jobs:
736736
DEBUG: pw:api
737737
CODER_E2E_LICENSE: ${{ secrets.CODER_E2E_LICENSE }}
738738
CODER_E2E_REQUIRE_PREMIUM_TESTS: "1"
739-
CODER_E2E_TEST_RETRIES: 2
740739
working-directory: site
741740

742741
- name: Upload Playwright Failed Tests
@@ -1406,7 +1405,7 @@ jobs:
14061405
uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a # v2.1.4
14071406

14081407
- name: Set up Flux CLI
1409-
uses: fluxcd/flux2/action@bda4c8187e436462be0d072e728b67afa215c593 # v2.6.3
1408+
uses: fluxcd/flux2/action@6bf37f6a560fd84982d67f853162e4b3c2235edb # v2.6.4
14101409
with:
14111410
# Keep this and the github action up to date with the version of flux installed in dogfood cluster
14121411
version: "2.5.1"

.github/workflows/docs-ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
- name: Setup Node
2929
uses: ./.github/actions/setup-node
3030

31-
- uses: tj-actions/changed-files@cf79a64fed8a943fb1073260883d08fe0dfb4e56 # v45.0.7
31+
- uses: tj-actions/changed-files@055970845dd036d7345da7399b7e89f2e10f2b04 # v45.0.7
3232
id: changed-files
3333
with:
3434
files: |

.github/workflows/release.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,29 @@ jobs:
634634
- name: ls build
635635
run: ls -lh build
636636

637+
- name: Publish Coder CLI binaries and detached signatures to GCS
638+
if: ${{ !inputs.dry_run && github.ref == 'refs/heads/main' && github.repository_owner == 'coder'}}
639+
run: |
640+
set -euxo pipefail
641+
642+
version="$(./scripts/version.sh)"
643+
644+
binaries=(
645+
"coder-darwin-amd64"
646+
"coder-darwin-arm64"
647+
"coder-linux-amd64"
648+
"coder-linux-arm64"
649+
"coder-linux-armv7"
650+
"coder-windows-amd64.exe"
651+
"coder-windows-arm64.exe"
652+
)
653+
654+
for binary in "${binaries[@]}"; do
655+
detached_signature="${binary}.asc"
656+
gcloud storage cp "./site/out/bin/${binary}" "gs://releases.coder.com/coder-cli/${version}/${binary}"
657+
gcloud storage cp "./site/out/bin/${detached_signature}" "gs://releases.coder.com/coder-cli/${version}/${detached_signature}"
658+
done
659+
637660
- name: Publish release
638661
run: |
639662
set -euo pipefail

.github/workflows/start-workspace.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
timeout-minutes: 5
2020
steps:
2121
- name: Start Coder workspace
22-
uses: coder/start-workspace-action@35a4608cefc7e8cc56573cae7c3b85304575cb72
22+
uses: coder/start-workspace-action@f97a681b4cc7985c9eef9963750c7cc6ebc93a19
2323
with:
2424
github-token: ${{ secrets.GITHUB_TOKEN }}
2525
github-username: >-

agent/agentcontainers/api.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package agentcontainers
22

33
import (
44
"context"
5+
"encoding/json"
56
"errors"
67
"fmt"
8+
"maps"
79
"net/http"
810
"os"
911
"path"
@@ -30,6 +32,7 @@ import (
3032
"github.com/coder/coder/v2/codersdk/agentsdk"
3133
"github.com/coder/coder/v2/provisioner"
3234
"github.com/coder/quartz"
35+
"github.com/coder/websocket"
3336
)
3437

3538
const (
@@ -74,6 +77,7 @@ type API struct {
7477

7578
mu sync.RWMutex // Protects the following fields.
7679
initDone chan struct{} // Closed by Init.
80+
updateChans []chan struct{}
7781
closed bool
7882
containers codersdk.WorkspaceAgentListContainersResponse // Output from the last list operation.
7983
containersErr error // Error from the last list operation.
@@ -535,6 +539,7 @@ func (api *API) Routes() http.Handler {
535539
r.Use(ensureInitDoneMW)
536540

537541
r.Get("/", api.handleList)
542+
r.Get("/watch", api.watchContainers)
538543
// TODO(mafredri): Simplify this route as the previous /devcontainers
539544
// /-route was dropped. We can drop the /devcontainers prefix here too.
540545
r.Route("/devcontainers/{devcontainer}", func(r chi.Router) {
@@ -544,6 +549,88 @@ func (api *API) Routes() http.Handler {
544549
return r
545550
}
546551

552+
func (api *API) broadcastUpdatesLocked() {
553+
// Broadcast state changes to WebSocket listeners.
554+
for _, ch := range api.updateChans {
555+
select {
556+
case ch <- struct{}{}:
557+
default:
558+
}
559+
}
560+
}
561+
562+
func (api *API) watchContainers(rw http.ResponseWriter, r *http.Request) {
563+
ctx := r.Context()
564+
565+
conn, err := websocket.Accept(rw, r, nil)
566+
if err != nil {
567+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
568+
Message: "Failed to upgrade connection to websocket.",
569+
Detail: err.Error(),
570+
})
571+
return
572+
}
573+
574+
// Here we close the websocket for reading, so that the websocket library will handle pings and
575+
// close frames.
576+
_ = conn.CloseRead(context.Background())
577+
578+
ctx, wsNetConn := codersdk.WebsocketNetConn(ctx, conn, websocket.MessageText)
579+
defer wsNetConn.Close()
580+
581+
go httpapi.Heartbeat(ctx, conn)
582+
583+
updateCh := make(chan struct{}, 1)
584+
585+
api.mu.Lock()
586+
api.updateChans = append(api.updateChans, updateCh)
587+
api.mu.Unlock()
588+
589+
defer func() {
590+
api.mu.Lock()
591+
api.updateChans = slices.DeleteFunc(api.updateChans, func(ch chan struct{}) bool {
592+
return ch == updateCh
593+
})
594+
close(updateCh)
595+
api.mu.Unlock()
596+
}()
597+
598+
encoder := json.NewEncoder(wsNetConn)
599+
600+
ct, err := api.getContainers()
601+
if err != nil {
602+
api.logger.Error(ctx, "unable to get containers", slog.Error(err))
603+
return
604+
}
605+
606+
if err := encoder.Encode(ct); err != nil {
607+
api.logger.Error(ctx, "encode container list", slog.Error(err))
608+
return
609+
}
610+
611+
for {
612+
select {
613+
case <-api.ctx.Done():
614+
return
615+
616+
case <-ctx.Done():
617+
return
618+
619+
case <-updateCh:
620+
ct, err := api.getContainers()
621+
if err != nil {
622+
api.logger.Error(ctx, "unable to get containers", slog.Error(err))
623+
continue
624+
}
625+
626+
if err := encoder.Encode(ct); err != nil {
627+
api.logger.Error(ctx, "encode container list", slog.Error(err))
628+
return
629+
}
630+
}
631+
}
632+
}
633+
547634
// handleList handles the HTTP request to list containers.
548635
func (api *API) handleList(rw http.ResponseWriter, r *http.Request) {
549636
ct, err := api.getContainers()
@@ -583,8 +670,26 @@ func (api *API) updateContainers(ctx context.Context) error {
583670
api.mu.Lock()
584671
defer api.mu.Unlock()
585672

673+
var previouslyKnownDevcontainers map[string]codersdk.WorkspaceAgentDevcontainer
674+
if len(api.updateChans) > 0 {
675+
previouslyKnownDevcontainers = maps.Clone(api.knownDevcontainers)
676+
}
677+
586678
api.processUpdatedContainersLocked(ctx, updated)
587679

680+
if len(api.updateChans) > 0 {
681+
statesAreEqual := maps.EqualFunc(
682+
previouslyKnownDevcontainers,
683+
api.knownDevcontainers,
684+
func(dc1, dc2 codersdk.WorkspaceAgentDevcontainer) bool {
685+
return dc1.Equals(dc2)
686+
})
687+
688+
if !statesAreEqual {
689+
api.broadcastUpdatesLocked()
690+
}
691+
}
692+
588693
api.logger.Debug(ctx, "containers updated successfully", slog.F("container_count", len(api.containers.Containers)), slog.F("warning_count", len(api.containers.Warnings)), slog.F("devcontainer_count", len(api.knownDevcontainers)))
589694

590695
return nil
@@ -955,6 +1060,8 @@ func (api *API) handleDevcontainerRecreate(w http.ResponseWriter, r *http.Reques
9551060
dc.Container = nil
9561061
dc.Error = ""
9571062
api.knownDevcontainers[dc.WorkspaceFolder] = dc
1063+
api.broadcastUpdatesLocked()
1064+
9581065
go func() {
9591066
_ = api.CreateDevcontainer(dc.WorkspaceFolder, dc.ConfigPath, WithRemoveExistingContainer())
9601067
}()
@@ -1070,6 +1177,7 @@ func (api *API) CreateDevcontainer(workspaceFolder, configPath string, opts ...D
10701177
dc.Error = ""
10711178
api.recreateSuccessTimes[dc.WorkspaceFolder] = api.clock.Now("agentcontainers", "recreate", "successTimes")
10721179
api.knownDevcontainers[dc.WorkspaceFolder] = dc
1180+
api.broadcastUpdatesLocked()
10731181
api.mu.Unlock()
10741182

10751183
// Ensure an immediate refresh to accurately reflect the

0 commit comments

Comments
 (0)