Skip to content

Commit

Permalink
[.gitpod.yml] Introduce top-level env (#20339)
Browse files Browse the repository at this point in the history
* [.gitpod.yml] Introduce top-level `env`

* Update priority (prioritize User level vars)
  • Loading branch information
filiptronicek authored Nov 5, 2024
1 parent c0c9b74 commit 18b92d8
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 14 deletions.
7 changes: 7 additions & 0 deletions components/gitpod-protocol/data/gitpod-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,13 @@
"description": "the hard limit acts as a ceiling for the soft limit. For more details please check https://man7.org/linux/man-pages/man2/getrlimit.2.html"
}
}
},
"env": {
"type": "object",
"description": "Environment variables to set on the workspace.",
"additionalProperties": {
"type": "string"
}
}
},
"additionalProperties": false,
Expand Down
3 changes: 3 additions & 0 deletions components/gitpod-protocol/go/gitpod-config-types.go

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

1 change: 1 addition & 0 deletions components/gitpod-protocol/src/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,7 @@ export interface WorkspaceConfig {
jetbrains?: JetBrainsConfig;
coreDump?: CoreDumpConfig;
ideCredentials?: string;
env?: { [env: string]: any };

/** deprecated. Enabled by default **/
experimentalNetwork?: boolean;
Expand Down
33 changes: 23 additions & 10 deletions components/server/src/user/env-var-service.spec.db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
User,
UserEnvVarValue,
WithEnvvarsContext,
WorkspaceConfig,
} from "@gitpod/gitpod-protocol";
import { Experiments } from "@gitpod/gitpod-protocol/lib/experiments/configcat-server";
import * as chai from "chai";
Expand Down Expand Up @@ -43,36 +44,36 @@ const fooAnyUserEnvVar = {
name: "foo",
value: "any",
repositoryPattern: "gitpod/*",
};
} as const;

const barUserCommitEnvVar = {
name: "bar",
value: "commit",
repositoryPattern: "gitpod/gitpod-io",
};
} as const;

const barUserAnotherCommitEnvVar = {
name: "bar",
value: "commit",
repositoryPattern: "gitpod/openvscode-server",
};
} as const;

const barProjectCensoredEnvVar = {
name: "bar",
censored: true,
value: "project1",
};
} as const;

const bazProjectEnvVar = {
name: "baz",
censored: false,
value: "project2",
};
} as const;

const barContextEnvVar = {
name: "bar",
value: "context",
};
} as const;

const contextEnvVars = {
envvars: [barContextEnvVar],
Expand Down Expand Up @@ -299,15 +300,22 @@ describe("EnvVarService", async () => {
});
});

it("should resolve env variables regular projext", async () => {
it("should resolve env variables regular project", async () => {
await es.addUserEnvVar(member.id, member.id, fooAnyUserEnvVar);
await es.addUserEnvVar(member.id, member.id, barUserCommitEnvVar);
await es.addUserEnvVar(member.id, member.id, barUserAnotherCommitEnvVar);

await es.addProjectEnvVar(owner.id, project.id, barProjectCensoredEnvVar);
await es.addProjectEnvVar(owner.id, project.id, bazProjectEnvVar);

const envVars = await es.resolveEnvVariables(member.id, project.id, "regular", commitContext);
const workspaceConfig: WorkspaceConfig = {
env: {
foobar: "yes please",
[fooAnyUserEnvVar.name]: "overridden_by_user_var",
},
};

const envVars = await es.resolveEnvVariables(member.id, project.id, "regular", commitContext, workspaceConfig);
envVars.project.forEach((e) => {
delete (e as any).id;
delete (e as any).projectId;
Expand All @@ -327,10 +335,15 @@ describe("EnvVarService", async () => {
censored: e.censored,
})),
);
expect(envVars.workspace).to.have.deep.members([fooAnyUserEnvVar, barUserCommitEnvVar, bazProjectEnvVar]);
expect(envVars.workspace).to.have.deep.members([
fooAnyUserEnvVar,
barUserCommitEnvVar,
bazProjectEnvVar,
{ name: "foobar", value: "yes please" },
]);
});

it("should resolve env variables prebuild with projext ", async () => {
it("should resolve env variables prebuild with project", async () => {
await es.addUserEnvVar(member.id, member.id, fooAnyUserEnvVar);
await es.addUserEnvVar(member.id, member.id, barUserCommitEnvVar);
await es.addUserEnvVar(member.id, member.id, barUserAnotherCommitEnvVar);
Expand Down
19 changes: 15 additions & 4 deletions components/server/src/user/env-var-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
UserEnvVar,
UserEnvVarValue,
WithEnvvarsContext,
WorkspaceConfig,
WorkspaceContext,
WorkspaceType,
} from "@gitpod/gitpod-protocol";
Expand Down Expand Up @@ -231,6 +232,7 @@ export class EnvVarService {
projectId: string | undefined,
wsType: WorkspaceType,
wsContext: WorkspaceContext,
wsConfig?: WorkspaceConfig,
): Promise<ResolvedEnvVars> {
await this.auth.checkPermissionOnUser(requestorId, "read_env_var", requestorId);
if (projectId) {
Expand All @@ -249,7 +251,7 @@ export class EnvVarService {
: [];

if (wsType === "prebuild") {
// prebuild does not have access to user env vars and cannot be started via prewfix URL
// prebuild does not have access to user env vars and cannot be started via prefix URL
const withValues = await this.projectDB.getProjectEnvironmentVariableValues(projectEnvVars);
merge(withValues);
return {
Expand All @@ -258,14 +260,23 @@ export class EnvVarService {
};
}

// 1. first merge user envs
// 1. first merge the `env` in the .gitpod.yml
if (wsConfig?.env) {
const configEnvVars = Object.entries(wsConfig.env as Record<string, string>).map(([name, value]) => ({
name,
value,
}));
merge(configEnvVars);
}

// 2. then user envs
if (CommitContext.is(wsContext)) {
// this is a commit context, thus we can filter the env vars
const userEnvVars = await this.userDB.getEnvVars(requestorId);
merge(UserEnvVar.filter(userEnvVars, wsContext.repository.owner, wsContext.repository.name));
}

// 2. then from the project
// 3. then from the project
if (projectEnvVars.length) {
// Instead of using an access guard for Project environment variables, we let Project owners decide whether
// a variable should be:
Expand All @@ -276,7 +287,7 @@ export class EnvVarService {
merge(withValues);
}

// 3. then parsed from the context URL
// 4. then parsed from the context URL
if (WithEnvvarsContext.is(wsContext)) {
merge(wsContext.envvars);
}
Expand Down
1 change: 1 addition & 0 deletions components/server/src/workspace/gitpod-server-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
workspace.projectId,
workspace.type,
workspace.context,
workspace.config,
);

const result: EnvVarWithValue[] = [];
Expand Down
1 change: 1 addition & 0 deletions components/server/src/workspace/workspace-starter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ export class WorkspaceStarter {
workspace.projectId,
workspace.type,
workspace.context,
workspace.config,
);

await this.actuallyStartWorkspace(ctx, instance, workspace, user, envVars);
Expand Down

0 comments on commit 18b92d8

Please sign in to comment.