Skip to content

Commit 8f5748a

Browse files
committed
Merge branch 'main' of https://github.com/coder/coder into bq/upgrade-msw
2 parents a70d24c + f0c5e8e commit 8f5748a

File tree

263 files changed

+7060
-7876
lines changed

Some content is hidden

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

263 files changed

+7060
-7876
lines changed

.github/workflows/ci.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ jobs:
142142
143143
# Check for any typos
144144
- name: Check for typos
145-
uses: crate-ci/typos@v1.18.2
145+
uses: crate-ci/typos@v1.19.0
146146
with:
147147
config: .github/workflows/typos.toml
148148

@@ -155,7 +155,7 @@ jobs:
155155
156156
# Needed for helm chart linting
157157
- name: Install helm
158-
uses: azure/setup-helm@v3
158+
uses: azure/setup-helm@v4
159159
with:
160160
version: v3.9.2
161161

.github/workflows/security.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ jobs:
114114
echo "image=$(cat "$image_job")" >> $GITHUB_OUTPUT
115115
116116
- name: Run Trivy vulnerability scanner
117-
uses: aquasecurity/trivy-action@84384bd6e777ef152729993b8145ea352e9dd3ef
117+
uses: aquasecurity/trivy-action@062f2592684a31eb3aa050cc61e7ca1451cecd3d
118118
with:
119119
image-ref: ${{ steps.build.outputs.image }}
120120
format: sarif

.github/workflows/weekly-docs.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
file-path: "./README.md"
2525

2626
- name: Send Slack notification
27-
if: failure()
27+
if: failure() && github.event_name != 'workflow_dispatch'
2828
run: |
2929
curl -X POST -H 'Content-type: application/json' -d '{"msg":"Broken links found in the documentation. Please check the logs at ${{ env.LOGS_URL }}"}' ${{ secrets.DOCS_LINK_SLACK_WEBHOOK }}
3030
echo "Sent Slack notification"

README.md

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
[Quickstart](#quickstart) | [Docs](https://coder.com/docs) | [Why Coder](https://coder.com/why) | [Enterprise](https://coder.com/docs/v2/latest/enterprise)
2424

2525
[![discord](https://img.shields.io/discord/747933592273027093?label=discord)](https://discord.gg/coder)
26-
[![codecov](https://codecov.io/gh/coder/coder/branch/main/graph/badge.svg?token=TNLW3OAP6G)](https://codecov.io/gh/coder/coder)
2726
[![release](https://img.shields.io/github/v/release/coder/coder)](https://github.com/coder/coder/releases/latest)
2827
[![godoc](https://pkg.go.dev/badge/github.com/coder/coder.svg)](https://pkg.go.dev/github.com/coder/coder)
2928
[![Go Report Card](https://goreportcard.com/badge/github.com/coder/coder)](https://goreportcard.com/report/github.com/coder/coder)
@@ -53,8 +52,8 @@ curl -L https://coder.com/install.sh | sh
5352
# Start the Coder server (caches data in ~/.cache/coder)
5453
coder server
5554
56-
# Navigate to http://localhost:3000 to create your initial user
57-
# Create a Docker template, and provision a workspace
55+
# Navigate to http://localhost:3000 to create your initial user,
56+
# create a Docker template, and provision a workspace
5857
```
5958

6059
## Install
@@ -68,11 +67,11 @@ Releases.
6867
curl -L https://coder.com/install.sh | sh
6968
```
7069

71-
You can run the install script with `--dry-run` to see the commands that will be used to install without executing them. You can modify the installation process by including flags. Run the install script with `--help` for reference.
70+
You can run the install script with `--dry-run` to see the commands that will be used to install without executing them. Run the install script with `--help` for additional flags.
7271

7372
> See [install](https://coder.com/docs/v2/latest/install) for additional methods.
7473
75-
Once installed, you can start a production deployment<sup>1</sup> with a single command:
74+
Once installed, you can start a production deployment with a single command:
7675

7776
```shell
7877
# Automatically sets up an external access URL on *.try.coder.app
@@ -82,8 +81,6 @@ coder server
8281
coder server --postgres-url <url> --access-url <url>
8382
```
8483

85-
> <sup>1</sup> For production deployments, set up an external PostgreSQL instance for reliability.
86-
8784
Use `coder --help` to get a list of flags and environment variables. Use our [install guides](https://coder.com/docs/v2/latest/install) for a full walkthrough.
8885

8986
## Documentation
@@ -96,30 +93,26 @@ Browse our docs [here](https://coder.com/docs/v2) or visit a specific section be
9693
- [**Administration**](https://coder.com/docs/v2/latest/admin): Learn how to operate Coder
9794
- [**Enterprise**](https://coder.com/docs/v2/latest/enterprise): Learn about our paid features built for large teams
9895

99-
## Community and Support
96+
## Support
10097

10198
Feel free to [open an issue](https://github.com/coder/coder/issues/new) if you have questions, run into bugs, or have a feature request.
10299

103-
[Join our Discord](https://discord.gg/coder) or [Slack](https://cdr.co/join-community) to provide feedback on in-progress features, and chat with the community using Coder!
104-
105-
## Contributing
106-
107-
Contributions are welcome! Read the [contributing docs](https://coder.com/docs/v2/latest/CONTRIBUTING) to get started.
108-
109-
Find our list of contributors [here](https://github.com/coder/coder/graphs/contributors).
100+
[Join our Discord](https://discord.gg/coder) to provide feedback on in-progress features, and chat with the community using Coder!
110101

111-
## Related
102+
## Integrations
112103

113104
We are always working on new integrations. Feel free to open an issue to request an integration. Contributions are welcome in any official or community repositories.
114105

115106
### Official
116107

117108
- [**VS Code Extension**](https://marketplace.visualstudio.com/items?itemName=coder.coder-remote): Open any Coder workspace in VS Code with a single click
118109
- [**JetBrains Gateway Extension**](https://plugins.jetbrains.com/plugin/19620-coder): Open any Coder workspace in JetBrains Gateway with a single click
110+
- [**Dev Container Builder**](https://github.com/coder/envbuilder): Build development environments using `devcontainer.json` on Docker, Kubernetes, and OpenShift
111+
- [**Module Registry**](https://registry.coder.com): Extend development environments with common use-cases
112+
- [**Kubernetes Log Stream**](https://github.com/coder/coder-logstream-kube): Stream Kubernetes Pod events to the Coder startup logs
119113
- [**Self-Hosted VS Code Extension Marketplace**](https://github.com/coder/code-marketplace): A private extension marketplace that works in restricted or airgapped networks integrating with [code-server](https://github.com/coder/code-server).
120114

121115
### Community
122116

123117
- [**Provision Coder with Terraform**](https://github.com/ElliotG/coder-oss-tf): Provision Coder on Google GKE, Azure AKS, AWS EKS, DigitalOcean DOKS, IBMCloud K8s, OVHCloud K8s, and Scaleway K8s Kapsule with Terraform
124-
- [**Coder GitHub Action**](https://github.com/marketplace/actions/update-coder-template): A GitHub Action that updates Coder templates
125-
- [**Various Templates**](./examples/templates/community-templates.md): Hetzner Cloud, Docker in Docker, and other templates the community has built.
118+
- [**Coder Template GitHub Action**](https://github.com/marketplace/actions/update-coder-template): A GitHub Action that updates Coder templates

agent/agent.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/go-chi/chi/v5"
2626
"github.com/google/uuid"
2727
"github.com/prometheus/client_golang/prometheus"
28+
"github.com/prometheus/common/expfmt"
2829
"github.com/spf13/afero"
2930
"go.uber.org/atomic"
3031
"golang.org/x/exp/slices"
@@ -34,6 +35,7 @@ import (
3435
"tailscale.com/net/speedtest"
3536
"tailscale.com/tailcfg"
3637
"tailscale.com/types/netlogtype"
38+
"tailscale.com/util/clientmetric"
3739

3840
"cdr.dev/slog"
3941
"github.com/coder/retry"
@@ -1699,11 +1701,48 @@ func (a *agent) HandleHTTPMagicsockDebugLoggingState(w http.ResponseWriter, r *h
16991701
_, _ = fmt.Fprintf(w, "updated magicsock debug logging to %v", stateBool)
17001702
}
17011703

1704+
func (a *agent) HandleHTTPDebugManifest(w http.ResponseWriter, r *http.Request) {
1705+
sdkManifest := a.manifest.Load()
1706+
if sdkManifest == nil {
1707+
a.logger.Error(r.Context(), "no manifest in-memory")
1708+
w.WriteHeader(http.StatusInternalServerError)
1709+
_, _ = fmt.Fprintf(w, "no manifest in-memory")
1710+
return
1711+
}
1712+
1713+
w.WriteHeader(http.StatusOK)
1714+
if err := json.NewEncoder(w).Encode(sdkManifest); err != nil {
1715+
a.logger.Error(a.hardCtx, "write debug manifest", slog.Error(err))
1716+
}
1717+
}
1718+
1719+
func (a *agent) HandleHTTPDebugLogs(w http.ResponseWriter, r *http.Request) {
1720+
logPath := filepath.Join(a.logDir, "coder-agent.log")
1721+
f, err := os.Open(logPath)
1722+
if err != nil {
1723+
a.logger.Error(r.Context(), "open agent log file", slog.Error(err), slog.F("path", logPath))
1724+
w.WriteHeader(http.StatusInternalServerError)
1725+
_, _ = fmt.Fprintf(w, "could not open log file: %s", err)
1726+
return
1727+
}
1728+
defer f.Close()
1729+
1730+
// Limit to 10MB.
1731+
w.WriteHeader(http.StatusOK)
1732+
_, err = io.Copy(w, io.LimitReader(f, 10*1024*1024))
1733+
if err != nil && !errors.Is(err, io.EOF) {
1734+
a.logger.Error(r.Context(), "read agent log file", slog.Error(err))
1735+
return
1736+
}
1737+
}
1738+
17021739
func (a *agent) HTTPDebug() http.Handler {
17031740
r := chi.NewRouter()
17041741

1742+
r.Get("/debug/logs", a.HandleHTTPDebugLogs)
17051743
r.Get("/debug/magicsock", a.HandleHTTPDebugMagicsock)
17061744
r.Get("/debug/magicsock/debug-logging/{state}", a.HandleHTTPMagicsockDebugLoggingState)
1745+
r.Get("/debug/manifest", a.HandleHTTPDebugManifest)
17071746
r.NotFound(func(w http.ResponseWriter, r *http.Request) {
17081747
w.WriteHeader(http.StatusNotFound)
17091748
_, _ = w.Write([]byte("404 not found"))
@@ -1943,3 +1982,26 @@ func (a *apiConnRoutineManager) start(name string, b gracefulShutdownBehavior, f
19431982
func (a *apiConnRoutineManager) wait() error {
19441983
return a.eg.Wait()
19451984
}
1985+
1986+
func PrometheusMetricsHandler(prometheusRegistry *prometheus.Registry, logger slog.Logger) http.Handler {
1987+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1988+
w.Header().Set("Content-Type", "text/plain")
1989+
1990+
// Based on: https://github.com/tailscale/tailscale/blob/280255acae604796a1113861f5a84e6fa2dc6121/ipn/localapi/localapi.go#L489
1991+
clientmetric.WritePrometheusExpositionFormat(w)
1992+
1993+
metricFamilies, err := prometheusRegistry.Gather()
1994+
if err != nil {
1995+
logger.Error(context.Background(), "prometheus handler failed to gather metric families", slog.Error(err))
1996+
return
1997+
}
1998+
1999+
for _, metricFamily := range metricFamilies {
2000+
_, err = expfmt.MetricFamilyToText(w, metricFamily)
2001+
if err != nil {
2002+
logger.Error(context.Background(), "expfmt.MetricFamilyToText failed", slog.Error(err))
2003+
return
2004+
}
2005+
}
2006+
})
2007+
}

agent/agent_test.go

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import (
5555
"github.com/coder/coder/v2/agent/proto"
5656
"github.com/coder/coder/v2/codersdk"
5757
"github.com/coder/coder/v2/codersdk/agentsdk"
58+
"github.com/coder/coder/v2/cryptorand"
5859
"github.com/coder/coder/v2/pty/ptytest"
5960
"github.com/coder/coder/v2/tailnet"
6061
"github.com/coder/coder/v2/tailnet/tailnettest"
@@ -1974,11 +1975,21 @@ func TestAgent_WriteVSCodeConfigs(t *testing.T) {
19741975
func TestAgent_DebugServer(t *testing.T) {
19751976
t.Parallel()
19761977

1978+
logDir := t.TempDir()
1979+
logPath := filepath.Join(logDir, "coder-agent.log")
1980+
randLogStr, err := cryptorand.String(32)
1981+
require.NoError(t, err)
1982+
require.NoError(t, os.WriteFile(logPath, []byte(randLogStr), 0o600))
19771983
derpMap, _ := tailnettest.RunDERPAndSTUN(t)
19781984
//nolint:dogsled
19791985
conn, _, _, _, agnt := setupAgent(t, agentsdk.Manifest{
19801986
DERPMap: derpMap,
1981-
}, 0)
1987+
}, 0, func(c *agenttest.Client, o *agent.Options) {
1988+
o.ExchangeToken = func(context.Context) (string, error) {
1989+
return "token", nil
1990+
}
1991+
o.LogDir = logDir
1992+
})
19821993

19831994
awaitReachableCtx := testutil.Context(t, testutil.WaitLong)
19841995
ok := conn.AwaitReachable(awaitReachableCtx)
@@ -2059,6 +2070,40 @@ func TestAgent_DebugServer(t *testing.T) {
20592070
require.Contains(t, string(resBody), `invalid state "blah", must be a boolean`)
20602071
})
20612072
})
2073+
2074+
t.Run("Manifest", func(t *testing.T) {
2075+
t.Parallel()
2076+
2077+
ctx := testutil.Context(t, testutil.WaitLong)
2078+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, srv.URL+"/debug/manifest", nil)
2079+
require.NoError(t, err)
2080+
2081+
res, err := srv.Client().Do(req)
2082+
require.NoError(t, err)
2083+
defer res.Body.Close()
2084+
require.Equal(t, http.StatusOK, res.StatusCode)
2085+
2086+
var v agentsdk.Manifest
2087+
require.NoError(t, json.NewDecoder(res.Body).Decode(&v))
2088+
require.NotNil(t, v)
2089+
})
2090+
2091+
t.Run("Logs", func(t *testing.T) {
2092+
t.Parallel()
2093+
2094+
ctx := testutil.Context(t, testutil.WaitLong)
2095+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, srv.URL+"/debug/logs", nil)
2096+
require.NoError(t, err)
2097+
2098+
res, err := srv.Client().Do(req)
2099+
require.NoError(t, err)
2100+
require.Equal(t, http.StatusOK, res.StatusCode)
2101+
defer res.Body.Close()
2102+
resBody, err := io.ReadAll(res.Body)
2103+
require.NoError(t, err)
2104+
require.NotEmpty(t, string(resBody))
2105+
require.Contains(t, string(resBody), randLogStr)
2106+
})
20622107
}
20632108

20642109
func TestAgent_ScriptLogging(t *testing.T) {

agent/api.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,13 @@ func (a *agent) apiHandler() http.Handler {
3535
ignorePorts: cpy,
3636
cacheDuration: cacheDuration,
3737
}
38+
promHandler := PrometheusMetricsHandler(a.prometheusRegistry, a.logger)
3839
r.Get("/api/v0/listening-ports", lp.handler)
40+
r.Get("/debug/logs", a.HandleHTTPDebugLogs)
3941
r.Get("/debug/magicsock", a.HandleHTTPDebugMagicsock)
4042
r.Get("/debug/magicsock/debug-logging/{state}", a.HandleHTTPMagicsockDebugLoggingState)
43+
r.Get("/debug/manifest", a.HandleHTTPDebugManifest)
44+
r.Get("/debug/prometheus", promHandler.ServeHTTP)
4145

4246
return r
4347
}

0 commit comments

Comments
 (0)