Skip to content

[pull] main from coder:main #109

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

Merged
merged 2 commits into from
Jul 23, 2025
Merged
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
6 changes: 4 additions & 2 deletions codersdk/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ import (
// These cookies are Coder-specific. If a new one is added or changed, the name
// shouldn't be likely to conflict with any user-application set cookies.
// Be sure to strip additional cookies in httpapi.StripCoderCookies!
// SessionTokenCookie represents the name of the cookie or query parameter the API key is stored in.
// NOTE: This is declared as a var so that we can override it in `develop.sh` if required.
var SessionTokenCookie = "coder_session_token"

const (
// SessionTokenCookie represents the name of the cookie or query parameter the API key is stored in.
SessionTokenCookie = "coder_session_token"
// SessionTokenHeader is the custom header to use for authentication.
SessionTokenHeader = "Coder-Session-Token"
// OAuth2StateCookie is the name of the cookie that stores the oauth2 state.
Expand Down
8 changes: 8 additions & 0 deletions scripts/build_go.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ boringcrypto=${CODER_BUILD_BORINGCRYPTO:-0}
dylib=0
windows_resources="${CODER_WINDOWS_RESOURCES:-0}"
debug=0
develop_in_coder="${DEVELOP_IN_CODER:-0}"

bin_ident="com.coder.cli"

Expand Down Expand Up @@ -149,6 +150,13 @@ if [[ "$debug" == 0 ]]; then
ldflags+=(-s -w)
fi

if [[ "$develop_in_coder" == 1 ]]; then
echo "INFO : Overriding codersdk.SessionTokenCookie as we are developing inside a Coder workspace."
ldflags+=(
-X "'github.com/coder/coder/v2/codersdk.SessionTokenCookie=dev_coder_session_token'"
)
fi

# We use ts_omit_aws here because on Linux it prevents Tailscale from importing
# github.com/aws/aws-sdk-go-v2/aws, which adds 7 MB to the binary.
TS_EXTRA_SMALL="ts_omit_aws,ts_omit_bird,ts_omit_tap,ts_omit_kube"
Expand Down
10 changes: 8 additions & 2 deletions scripts/coder-dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ source "${SCRIPT_DIR}/lib.sh"

GOOS="$(go env GOOS)"
GOARCH="$(go env GOARCH)"
CODER_AGENT_URL="${CODER_AGENT_URL:-}"
DEVELOP_IN_CODER="${DEVELOP_IN_CODER:-0}"
DEBUG_DELVE="${DEBUG_DELVE:-0}"
BINARY_TYPE=coder-slim
if [[ ${1:-} == server ]]; then
Expand All @@ -35,16 +37,20 @@ CODER_DEV_DIR="$(realpath ./.coderv2)"
CODER_DELVE_DEBUG_BIN=$(realpath "./build/coder_debug_${GOOS}_${GOARCH}")
popd

if [ -n "${CODER_AGENT_URL}" ]; then
DEVELOP_IN_CODER=1
fi

case $BINARY_TYPE in
coder-slim)
# Ensure the coder slim binary is always up-to-date with local
# changes, this simplifies usage of this script for development.
# NOTE: we send all output of `make` to /dev/null so that we do not break
# scripts that read the output of this command.
if [[ -t 1 ]]; then
make -j "${RELATIVE_BINARY_PATH}"
DEVELOP_IN_CODER="${DEVELOP_IN_CODER}" make -j "${RELATIVE_BINARY_PATH}"
else
make -j "${RELATIVE_BINARY_PATH}" >/dev/null 2>&1
DEVELOP_IN_CODER="${DEVELOP_IN_CODER}" make -j "${RELATIVE_BINARY_PATH}" >/dev/null 2>&1
fi
;;
coder)
Expand Down
9 changes: 7 additions & 2 deletions scripts/develop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ source "${SCRIPT_DIR}/lib.sh"
set -euo pipefail

CODER_DEV_ACCESS_URL="${CODER_DEV_ACCESS_URL:-http://127.0.0.1:3000}"
DEVELOP_IN_CODER="${DEVELOP_IN_CODER:-0}"
debug=0
DEFAULT_PASSWORD="SomeSecurePassword!"
password="${CODER_DEV_ADMIN_PASSWORD:-${DEFAULT_PASSWORD}}"
Expand Down Expand Up @@ -66,6 +67,10 @@ if [ "${CODER_BUILD_AGPL:-0}" -gt "0" ] && [ "${multi_org}" -gt "0" ]; then
echo '== ERROR: cannot use both multi-organizations and APGL build.' && exit 1
fi

if [ -n "${CODER_AGENT_URL}" ]; then
DEVELOP_IN_CODER=1
fi

# Preflight checks: ensure we have our required dependencies, and make sure nothing is listening on port 3000 or 8080
dependencies curl git go make pnpm
curl --fail http://127.0.0.1:3000 >/dev/null 2>&1 && echo '== ERROR: something is listening on port 3000. Kill it and re-run this script.' && exit 1
Expand All @@ -75,7 +80,7 @@ curl --fail http://127.0.0.1:8080 >/dev/null 2>&1 && echo '== ERROR: something i
# node_modules if necessary.
GOOS="$(go env GOOS)"
GOARCH="$(go env GOARCH)"
make -j "build/coder_${GOOS}_${GOARCH}"
DEVELOP_IN_CODER="${DEVELOP_IN_CODER}" make -j "build/coder_${GOOS}_${GOARCH}"

# Use the coder dev shim so we don't overwrite the user's existing Coder config.
CODER_DEV_SHIM="${PROJECT_ROOT}/scripts/coder-dev.sh"
Expand Down Expand Up @@ -150,7 +155,7 @@ fatal() {
trap 'fatal "Script encountered an error"' ERR

cdroot
DEBUG_DELVE="${debug}" start_cmd API "" "${CODER_DEV_SHIM}" server --http-address 0.0.0.0:3000 --swagger-enable --access-url "${CODER_DEV_ACCESS_URL}" --dangerous-allow-cors-requests=true --enable-terraform-debug-mode "$@"
DEBUG_DELVE="${debug}" DEVELOP_IN_CODER="${DEVELOP_IN_CODER}" start_cmd API "" "${CODER_DEV_SHIM}" server --http-address 0.0.0.0:3000 --swagger-enable --access-url "${CODER_DEV_ACCESS_URL}" --dangerous-allow-cors-requests=true --enable-terraform-debug-mode "$@"

echo '== Waiting for Coder to become ready'
# Start the timeout in the background so interrupting this script
Expand Down
7 changes: 7 additions & 0 deletions site/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ const getMissingParameters = (
return missingParameters;
};

/**
* Originally from codersdk/client.go.
* The below declaration is required to stop Knip from complaining.
* @public
*/
export const SessionTokenCookie = "coder_session_token";

/**
* @param agentId
* @returns {OneWayWebSocket} A OneWayWebSocket that emits Server-Sent Events.
Expand Down
3 changes: 0 additions & 3 deletions site/src/api/typesGenerated.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ const CreateWorkspacePage: FC = () => {
});
const permissionsQuery = useQuery({
...checkAuthorization({
checks: createWorkspaceChecks(templateQuery.data?.organization_id ?? ""),
checks: createWorkspaceChecks(
templateQuery.data?.organization_id ?? "",
templateQuery.data?.id,
),
}),
enabled: !!templateQuery.data,
});
Expand Down Expand Up @@ -208,6 +211,7 @@ const CreateWorkspacePage: FC = () => {
startPollingExternalAuth={startPollingExternalAuth}
hasAllRequiredExternalAuth={hasAllRequiredExternalAuth}
permissions={permissionsQuery.data as CreateWorkspacePermissions}
canUpdateTemplate={permissionsQuery.data?.canUpdateTemplate}
parameters={realizedParameters as TemplateVersionParameter[]}
presets={templateVersionPresetsQuery.data ?? []}
creatingWorkspace={createWorkspaceMutation.isPending}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,10 @@ const CreateWorkspacePageExperimental: FC = () => {
});
const permissionsQuery = useQuery({
...checkAuthorization({
checks: createWorkspaceChecks(templateQuery.data?.organization_id ?? ""),
checks: createWorkspaceChecks(
templateQuery.data?.organization_id ?? "",
templateQuery.data?.id,
),
}),
enabled: !!templateQuery.data,
});
Expand Down Expand Up @@ -292,6 +295,7 @@ const CreateWorkspacePageExperimental: FC = () => {
owner={owner}
setOwner={setOwner}
autofillParameters={autofillParameters}
canUpdateTemplate={permissionsQuery.data?.canUpdateTemplate}
error={
wsError ||
createWorkspaceMutation.error ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const meta: Meta<typeof CreateWorkspacePageView> = {
mode: "form",
permissions: {
createWorkspaceForAny: true,
canUpdateTemplate: false,
},
onCancel: action("onCancel"),
},
Expand Down Expand Up @@ -382,3 +383,23 @@ export const ExternalAuthAllConnected: Story = {
],
},
};

export const WithViewSourceButton: Story = {
args: {
canUpdateTemplate: true,
versionId: "template-version-123",
template: {
...MockTemplate,
organization_name: "default",
name: "docker-template",
},
},
parameters: {
docs: {
description: {
story:
"This story shows the View Source button that appears for template administrators. The button allows quick navigation to the template editor from the workspace creation page.",
},
},
},
};
22 changes: 19 additions & 3 deletions site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ import { Switch } from "components/Switch/Switch";
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete";
import { type FormikContextType, useFormik } from "formik";
import type { ExternalAuthPollingState } from "hooks/useExternalAuth";
import { ExternalLinkIcon } from "lucide-react";
import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName";
import { type FC, useCallback, useEffect, useMemo, useState } from "react";
import { Link } from "react-router-dom";
import {
getFormHelpers,
nameValidator,
Expand Down Expand Up @@ -67,6 +69,7 @@ interface CreateWorkspacePageViewProps {
presets: TypesGen.Preset[];
permissions: CreateWorkspacePermissions;
creatingWorkspace: boolean;
canUpdateTemplate?: boolean;
onCancel: () => void;
onSubmit: (
req: TypesGen.CreateWorkspaceRequest,
Expand All @@ -92,6 +95,7 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({
presets = [],
permissions,
creatingWorkspace,
canUpdateTemplate,
onSubmit,
onCancel,
}) => {
Expand Down Expand Up @@ -218,9 +222,21 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({
<Margins size="medium">
<PageHeader
actions={
<Button size="sm" variant="outline" onClick={onCancel}>
Cancel
</Button>
<Stack direction="row" spacing={2}>
{canUpdateTemplate && (
<Button asChild size="sm" variant="outline">
<Link
to={`/templates/${template.organization_name}/${template.name}/versions/${versionId}/edit`}
>
<ExternalLinkIcon />
View source
</Link>
</Button>
)}
<Button size="sm" variant="outline" onClick={onCancel}>
Cancel
</Button>
</Stack>
}
>
<Stack direction="row">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const meta: Meta<typeof CreateWorkspacePageViewExperimental> = {
parameters: [],
permissions: {
createWorkspaceForAny: true,
canUpdateTemplate: false,
},
presets: [],
sendMessage: () => {},
Expand All @@ -38,3 +39,23 @@ export const WebsocketError: Story = {
),
},
};

export const WithViewSourceButton: Story = {
args: {
canUpdateTemplate: true,
versionId: "template-version-123",
template: {
...MockTemplate,
organization_name: "default",
name: "docker-template",
},
},
parameters: {
docs: {
description: {
story:
"This story shows the View Source button that appears for template administrators in the experimental workspace creation page. The button allows quick navigation to the template editor.",
},
},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete";
import { type FormikContextType, useFormik } from "formik";
import type { ExternalAuthPollingState } from "hooks/useExternalAuth";
import { ArrowLeft, CircleHelp } from "lucide-react";
import { ArrowLeft, CircleHelp, ExternalLinkIcon } from "lucide-react";
import { useSyncFormParameters } from "modules/hooks/useSyncFormParameters";
import {
Diagnostics,
Expand All @@ -43,6 +43,7 @@ import {
useRef,
useState,
} from "react";
import { Link as RouterLink } from "react-router-dom";
import { docs } from "utils/docs";
import { nameValidator } from "utils/formUtils";
import type { AutofillBuildParameter } from "utils/richParameters";
Expand All @@ -53,6 +54,7 @@ import type { CreateWorkspacePermissions } from "./permissions";

interface CreateWorkspacePageViewExperimentalProps {
autofillParameters: AutofillBuildParameter[];
canUpdateTemplate?: boolean;
creatingWorkspace: boolean;
defaultName?: string | null;
defaultOwner: TypesGen.User;
Expand Down Expand Up @@ -84,6 +86,7 @@ export const CreateWorkspacePageViewExperimental: FC<
CreateWorkspacePageViewExperimentalProps
> = ({
autofillParameters,
canUpdateTemplate,
creatingWorkspace,
defaultName,
defaultOwner,
Expand Down Expand Up @@ -378,6 +381,16 @@ export const CreateWorkspacePageViewExperimental: FC<
</Badge>
)}
</span>
{canUpdateTemplate && (
<Button asChild size="sm" variant="outline">
<RouterLink
to={`/templates/${template.organization_name}/${template.name}/versions/${versionId}/edit`}
>
<ExternalLinkIcon />
View source
</RouterLink>
</Button>
)}
</div>
<span className="flex flex-row items-center gap-2">
<h1 className="text-3xl font-semibold m-0">New workspace</h1>
Expand Down
18 changes: 15 additions & 3 deletions site/src/pages/CreateWorkspacePage/permissions.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
export const createWorkspaceChecks = (organizationId: string) =>
export const createWorkspaceChecks = (
organizationId: string,
templateId?: string,
) =>
({
createWorkspaceForAny: {
object: {
resource_type: "workspace",
resource_type: "workspace" as const,
organization_id: organizationId,
owner_id: "*",
},
action: "create",
action: "create" as const,
},
...(templateId && {
canUpdateTemplate: {
object: {
resource_type: "template" as const,
resource_id: templateId,
},
action: "update" as const,
},
}),
}) as const;

export type CreateWorkspacePermissions = Record<
Expand Down
2 changes: 1 addition & 1 deletion site/vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export default defineConfig({
secure: process.env.NODE_ENV === "production",
},
},
allowedHosts: [".coder"],
allowedHosts: [".coder", ".dev.coder.com"],
},
resolve: {
alias: {
Expand Down
Loading