Detailed changes
@@ -97,6 +97,8 @@ jobs:
with:
app-id: ${{ secrets.ZED_ZIPPY_APP_ID }}
private-key: ${{ secrets.ZED_ZIPPY_APP_PRIVATE_KEY }}
+ permission-contents: write
+ permission-workflows: write
- name: steps::checkout_repo
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
with:
@@ -35,6 +35,8 @@ jobs:
with:
app-id: ${{ secrets.ZED_ZIPPY_APP_ID }}
private-key: ${{ secrets.ZED_ZIPPY_APP_PRIVATE_KEY }}
+ permission-contents: write
+ permission-workflows: write
- name: cherry_pick::run_cherry_pick::cherry_pick
run: ./script/cherry-pick "$BRANCH" "$COMMIT" "$CHANNEL"
env:
@@ -2,7 +2,7 @@ use gh_workflow::*;
use crate::tasks::workflows::{
runners,
- steps::{self, FluentBuilder, NamedJob, named},
+ steps::{self, FluentBuilder, NamedJob, RepositoryTarget, TokenPermissions, named},
vars::{self, StepOutput, WorkflowInput},
};
@@ -161,7 +161,13 @@ fn commit_changes(pr_number: &WorkflowInput, autofix_job: &NamedJob) -> NamedJob
.add_env(("GITHUB_TOKEN", token))
}
- let (authenticate, token) = steps::authenticate_as_zippy();
+ let (authenticate, token) = steps::authenticate_as_zippy()
+ .for_repository(RepositoryTarget::current())
+ .with_permissions([
+ (TokenPermissions::Contents, Level::Write),
+ (TokenPermissions::Workflows, Level::Write),
+ ])
+ .into();
named::job(
Job::default()
@@ -63,7 +63,7 @@ fn run_bump_patch_version(branch: &WorkflowInput) -> steps::NamedJob {
.add_env(("GITHUB_TOKEN", token))
}
- let (authenticate, token) = steps::authenticate_as_zippy();
+ let (authenticate, token) = steps::authenticate_as_zippy().into();
named::job(
Job::default()
@@ -2,7 +2,7 @@ use gh_workflow::*;
use crate::tasks::workflows::{
runners,
- steps::{self, NamedJob, named},
+ steps::{self, NamedJob, RepositoryTarget, TokenPermissions, named},
vars::{StepOutput, WorkflowInput},
};
@@ -44,7 +44,13 @@ fn run_cherry_pick(
.add_env(("GITHUB_TOKEN", token))
}
- let (authenticate, token) = steps::authenticate_as_zippy();
+ let (authenticate, token) = steps::authenticate_as_zippy()
+ .for_repository(RepositoryTarget::current())
+ .with_permissions([
+ (TokenPermissions::Contents, Level::Write),
+ (TokenPermissions::Workflows, Level::Write),
+ ])
+ .into();
named::job(
Job::default()
@@ -359,7 +359,8 @@ fn trigger_release(
let extension_registry = RepositoryTarget::new("zed-industries", &["extensions"]);
let (generate_token, generated_token) =
generate_token(&app_id.to_string(), &app_secret.to_string())
- .for_repository(extension_registry);
+ .for_repository(extension_registry)
+ .into();
let (get_extension_id, extension_id) = get_extension_id();
let (release_action, pull_request_number) = release_action(extension_id, tag, &generated_token);
@@ -6,6 +6,7 @@ use indoc::indoc;
use serde_json::json;
use crate::tasks::workflows::steps::CheckoutStep;
+use crate::tasks::workflows::steps::TokenPermissions;
use crate::tasks::workflows::steps::cache_rust_dependencies_namespace;
use crate::tasks::workflows::vars::JobOutput;
use crate::tasks::workflows::{
@@ -309,13 +310,17 @@ fn rollout_workflows_to_extension(
}
let (authenticate, token) =
- generate_token(vars::ZED_ZIPPY_APP_ID, vars::ZED_ZIPPY_APP_PRIVATE_KEY).for_repository(
- RepositoryTarget::new("zed-extensions", &["${{ matrix.repo }}"]).permissions([
- ("permission-pull-requests".to_owned(), Level::Write),
- ("permission-contents".to_owned(), Level::Write),
- ("permission-workflows".to_owned(), Level::Write),
- ]),
- );
+ generate_token(vars::ZED_ZIPPY_APP_ID, vars::ZED_ZIPPY_APP_PRIVATE_KEY)
+ .for_repository(RepositoryTarget::new(
+ "zed-extensions",
+ &["${{ matrix.repo }}"],
+ ))
+ .with_permissions([
+ (TokenPermissions::PullRequests, Level::Write),
+ (TokenPermissions::Contents, Level::Write),
+ (TokenPermissions::Workflows, Level::Write),
+ ])
+ .into();
let (calculate_short_sha, short_sha) = get_short_sha();
@@ -372,10 +377,10 @@ fn create_rollout_tag(rollout_job: &NamedJob, filter_repos_input: &WorkflowInput
}
let (authenticate, token) =
- generate_token(vars::ZED_ZIPPY_APP_ID, vars::ZED_ZIPPY_APP_PRIVATE_KEY).for_repository(
- RepositoryTarget::current()
- .permissions([("permission-contents".to_owned(), Level::Write)]),
- );
+ generate_token(vars::ZED_ZIPPY_APP_ID, vars::ZED_ZIPPY_APP_PRIVATE_KEY)
+ .for_repository(RepositoryTarget::current())
+ .with_permissions([(TokenPermissions::Contents, Level::Write)])
+ .into();
let job = Job::default()
.needs([rollout_job.name.clone()])
@@ -119,7 +119,8 @@ fn update_sha_in_extensions(publish_job: &NamedJob) -> NamedJob {
let extensions_repo = RepositoryTarget::new("zed-industries", &["extensions"]);
let (generate_token, generated_token) =
generate_token(vars::ZED_ZIPPY_APP_ID, vars::ZED_ZIPPY_APP_PRIVATE_KEY)
- .for_repository(extensions_repo);
+ .for_repository(extensions_repo)
+ .into();
fn checkout_extensions_repo(token: &StepOutput) -> Step<Use> {
named::uses(
@@ -179,7 +179,7 @@ fn validate_release_assets(deps: &[&NamedJob]) -> NamedJob {
}
fn auto_release_preview(deps: &[&NamedJob]) -> NamedJob {
- let (authenticate, token) = steps::authenticate_as_zippy();
+ let (authenticate, token) = steps::authenticate_as_zippy().into();
named::job(
dependant_job(deps)
@@ -513,20 +513,50 @@ pub fn git_checkout(ref_name: &dyn std::fmt::Display) -> Step<Run> {
.add_env(("REF_NAME", ref_name.to_string()))
}
+/// Non-exhaustive list of the permissions to be set for a GitHub app token.
+///
+/// See https://github.com/actions/create-github-app-token?tab=readme-ov-file#permission-permission-name
+/// and beyond for a full list of available permissions.
+#[allow(unused)]
+pub(crate) enum TokenPermissions {
+ Contents,
+ Issues,
+ PullRequests,
+ Workflows,
+}
+
+impl TokenPermissions {
+ pub fn environment_name(&self) -> &'static str {
+ match self {
+ TokenPermissions::Contents => "permission-contents",
+ TokenPermissions::Issues => "permission-issues",
+ TokenPermissions::PullRequests => "permission-pull-requests",
+ TokenPermissions::Workflows => "permission-workflows",
+ }
+ }
+}
+
pub(crate) struct GenerateAppToken<'a> {
job_name: String,
app_id: &'a str,
app_secret: &'a str,
repository_target: Option<RepositoryTarget>,
+ permissions: Option<Vec<(TokenPermissions, Level)>>,
}
impl<'a> GenerateAppToken<'a> {
- pub fn for_repository(self, repository_target: RepositoryTarget) -> (Step<Use>, StepOutput) {
+ pub fn for_repository(self, repository_target: RepositoryTarget) -> Self {
Self {
repository_target: Some(repository_target),
..self
}
- .into()
+ }
+
+ pub fn with_permissions(self, permissions: impl Into<Vec<(TokenPermissions, Level)>>) -> Self {
+ Self {
+ permissions: Some(permissions.into()),
+ ..self
+ }
}
}
@@ -549,26 +579,24 @@ impl<'a> From<GenerateAppToken<'a>> for (Step<Use>, StepOutput) {
RepositoryTarget {
owner,
repositories,
- permissions,
}| {
input
.when_some(owner, |input, owner| input.add("owner", owner))
.when_some(repositories, |input, repositories| {
input.add("repositories", repositories)
})
- .when_some(permissions, |input, permissions| {
- permissions.into_iter().fold(
- input,
- |input, (permission, level)| {
- input.add(
- permission,
- serde_json::to_value(&level).unwrap_or_default(),
- )
- },
- )
- })
},
- ),
+ )
+ .when_some(token.permissions, |input, permissions| {
+ permissions
+ .into_iter()
+ .fold(input, |input, (permission, level)| {
+ input.add(
+ permission.environment_name(),
+ serde_json::to_value(&level).unwrap_or_default(),
+ )
+ })
+ }),
);
let generated_token = StepOutput::new(&step, "token");
@@ -579,7 +607,6 @@ impl<'a> From<GenerateAppToken<'a>> for (Step<Use>, StepOutput) {
pub(crate) struct RepositoryTarget {
owner: Option<String>,
repositories: Option<String>,
- permissions: Option<Vec<(String, Level)>>,
}
impl RepositoryTarget {
@@ -587,7 +614,6 @@ impl RepositoryTarget {
Self {
owner: Some(owner.to_string()),
repositories: Some(repositories.join("\n")),
- permissions: None,
}
}
@@ -595,14 +621,6 @@ impl RepositoryTarget {
Self {
owner: None,
repositories: None,
- permissions: None,
- }
- }
-
- pub fn permissions(self, permissions: impl Into<Vec<(String, Level)>>) -> Self {
- Self {
- permissions: Some(permissions.into()),
- ..self
}
}
}
@@ -614,8 +632,8 @@ pub(crate) fn generate_token<'a>(
generate_token_with_job_name(app_id_source, app_secret_source)
}
-pub fn authenticate_as_zippy() -> (Step<Use>, StepOutput) {
- generate_token_with_job_name(vars::ZED_ZIPPY_APP_ID, vars::ZED_ZIPPY_APP_PRIVATE_KEY).into()
+pub fn authenticate_as_zippy() -> GenerateAppToken<'static> {
+ generate_token_with_job_name(vars::ZED_ZIPPY_APP_ID, vars::ZED_ZIPPY_APP_PRIVATE_KEY)
}
fn generate_token_with_job_name<'a>(
@@ -627,5 +645,6 @@ fn generate_token_with_job_name<'a>(
app_id: app_id_source,
app_secret: app_secret_source,
repository_target: None,
+ permissions: None,
}
}