Skip to content
Closed
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: 6 additions & 0 deletions lib/resolve-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default (
CI_PROJECT_URL,
CI_PROJECT_PATH,
CI_API_V4_URL,
CI_API_GRAPHQL_URL,
GL_TOKEN,
GITLAB_TOKEN,
GL_URL,
Expand Down Expand Up @@ -59,6 +60,11 @@ export default (
: service === "gitlab" && CI_API_V4_URL
? CI_API_V4_URL
: urlJoin(defaultedGitlabUrl, isNil(userGitlabApiPathPrefix) ? "/api/v4" : userGitlabApiPathPrefix),
gitlabGraphQlApiUrl: userGitlabUrl
? urlJoin(userGitlabUrl, "/graphql")
: service === "gitlab" && CI_API_GRAPHQL_URL
? CI_API_GRAPHQL_URL
: urlJoin(defaultedGitlabUrl, "/graphql"),
assets: assets ? castArray(assets) : assets,
milestones: milestones ? castArray(milestones) : milestones,
successComment,
Expand Down
64 changes: 49 additions & 15 deletions lib/verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ export default async (pluginConfig, context) => {
options: { repositoryUrl },
logger,
} = context;
const { gitlabToken, gitlabUrl, gitlabApiUrl, proxy, ...options } = resolveConfig(pluginConfig, context);
const { gitlabToken, gitlabUrl, gitlabApiUrl, gitlabGraphQlApiUrl, proxy, ...options } = resolveConfig(
pluginConfig,
context
);
const { projectPath, projectApiUrl } = getProjectContext(context, gitlabUrl, gitlabApiUrl, repositoryUrl);

debug("apiUrl: %o", gitlabApiUrl);
Expand All @@ -54,28 +57,59 @@ export default async (pluginConfig, context) => {
}

if (gitlabToken && projectPath) {
let projectAccess;
let groupAccess;

logger.log("Verify GitLab authentication (%s)", gitlabApiUrl);

try {
({
permissions: { project_access: projectAccess, group_access: groupAccess },
} = await got
// First, get basic project information to ensure the project exists
await got
.get(projectApiUrl, {
headers: { "PRIVATE-TOKEN": gitlabToken },
...proxy,
})
.json());
if (
context.options.dryRun &&
!((projectAccess && projectAccess.access_level >= 10) || (groupAccess && groupAccess.access_level >= 10))
) {
.json();

// Use GraphQL to check user permissions
debug("Checking permissions via GraphQL");
const query = `
query {
project(fullPath: "${projectPath}") {
userPermissions {
pushToRepository
readRepository
}
}
}
`;

const graphqlResponse = await got
.post(gitlabGraphQlApiUrl, {
headers: {
"Private-Token": gitlabToken,
"Content-Type": "application/json",
Accept: "application/graphql-response+json",
},
json: { query },
...proxy,
})
.json();

if (graphqlResponse.errors) {
debug("GraphQL query returned errors: %O", graphqlResponse.errors);
throw new Error(`GraphQL query failed: ${graphqlResponse.errors.map((e) => e.message).join(", ")}`);
}

const permissions = graphqlResponse.data?.project?.userPermissions;
if (!permissions) {
debug("No permissions data returned from GraphQL query");
throw new Error("Unable to determine permissions from GraphQL response");
}

debug("GraphQL permissions: %O", permissions);

// Check permissions based on GraphQL response
if (context.options.dryRun && !permissions.readRepository) {
errors.push(getError("EGLNOPULLPERMISSION", { projectPath }));
} else if (
!((projectAccess && projectAccess.access_level >= 30) || (groupAccess && groupAccess.access_level >= 30))
) {
} else if (!permissions.pushToRepository) {
errors.push(getError("EGLNOPUSHPERMISSION", { projectPath }));
}
} catch (error) {
Expand Down
11 changes: 11 additions & 0 deletions test/resolve-config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const defaultOptions = {
gitlabToken: undefined,
gitlabUrl: "https://gitlab.com",
gitlabApiUrl: urlJoin("https://gitlab.com", "/api/v4"),
gitlabGraphQlApiUrl: urlJoin("https://gitlab.com", "/graphql"),
assets: undefined,
milestones: undefined,
successComment: undefined,
Expand Down Expand Up @@ -41,6 +42,7 @@ test("Returns user config", (t) => {
gitlabToken,
gitlabUrl,
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
gitlabGraphQlApiUrl: urlJoin(gitlabUrl, "/graphql"),
assets,
labels: false,
retryLimit,
Expand All @@ -54,6 +56,7 @@ test("Returns user config", (t) => {
gitlabToken,
gitlabUrl,
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
gitlabGraphQlApiUrl: urlJoin(gitlabUrl, "/graphql"),
assets,
proxy,
}
Expand All @@ -77,6 +80,7 @@ test("Returns user config via environment variables", (t) => {
gitlabToken,
gitlabUrl,
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
gitlabGraphQlApiUrl: urlJoin(gitlabUrl, "/graphql"),
assets,
milestones,
}
Expand All @@ -96,6 +100,7 @@ test("Returns user config via alternative environment variables", (t) => {
gitlabToken,
gitlabUrl,
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
gitlabGraphQlApiUrl: urlJoin(gitlabUrl, "/graphql"),
assets,
milestones: undefined,
successComment: undefined,
Expand Down Expand Up @@ -223,6 +228,7 @@ test("Returns user config via alternative environment variables with mismatching
gitlabToken: "TOKEN",
gitlabUrl: "http://host.com",
gitlabApiUrl: "http://host.com/api/prefix",
gitlabGraphQlApiUrl: "http://host.com/graphql",
assets: ["file.js"],
}
);
Expand All @@ -245,6 +251,7 @@ test("Returns user config via alternative environment variables with mismatching
gitlabToken: "TOKEN",
gitlabUrl: "https://host.com",
gitlabApiUrl: "https://host.com/api/prefix",
gitlabGraphQlApiUrl: "https://host.com/graphql",
assets: ["file.js"],
}
);
Expand Down Expand Up @@ -387,6 +394,7 @@ test("Returns default config via GitLab CI/CD environment variables", (t) => {
gitlabToken,
gitlabUrl: "http://ci-host.com",
gitlabApiUrl: CI_API_V4_URL,
gitlabGraphQlApiUrl: "http://ci-host.com/graphql",
}
);
});
Expand Down Expand Up @@ -415,6 +423,7 @@ test("Returns user config over GitLab CI/CD environment variables", (t) => {
gitlabToken,
gitlabUrl,
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
gitlabGraphQlApiUrl: urlJoin(gitlabUrl, "/graphql"),
assets,
failTitle: "The automated release unfortunately failed!",
labels: "bot,release-failed",
Expand Down Expand Up @@ -450,6 +459,7 @@ test("Returns user config via environment variables over GitLab CI/CD environmen
gitlabToken,
gitlabUrl,
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
gitlabGraphQlApiUrl: urlJoin(gitlabUrl, "/graphql"),
}
);
});
Expand Down Expand Up @@ -482,6 +492,7 @@ test("Returns user config via alternative environment variables over GitLab CI/C
gitlabToken,
gitlabUrl,
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
gitlabGraphQlApiUrl: urlJoin(gitlabUrl, "/graphql"),
}
);
});
Expand Down
Loading