Skip to main content

cargo_dist/config/v1/ci/
github.rs

1//! github ci config
2
3use cargo_dist_schema::{
4    ContainerConfig, GithubRunner, GithubRunnerConfig, GithubRunnerConfigInput, StringLikeOr,
5    TripleName,
6};
7
8use crate::platform::{github_runners::target_for_github_runner, targets};
9
10use super::*;
11
12/// github ci config (raw from file)
13#[derive(Debug, Default, Clone, Serialize, Deserialize)]
14#[serde(rename_all = "kebab-case")]
15pub struct GithubCiLayer {
16    /// Common options
17    #[serde(flatten)]
18    pub common: CommonCiLayer,
19
20    /// Custom GitHub runners, mapped by triple target
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub runners: Option<SortedMap<TripleName, StringLikeOr<GithubRunner, GithubRunnerConfigInput>>>,
23
24    /// Custom permissions for jobs
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub permissions: Option<SortedMap<String, GithubPermissionMap>>,
27
28    /// Custom permissions for jobs
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub build_setup: Option<String>,
31
32    /// Use these commits for actions
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub action_commits: Option<SortedMap<String, String>>,
35}
36
37/// github ci config (final)
38#[derive(Debug, Default, Clone)]
39pub struct GithubCiConfig {
40    /// Common options
41    pub common: CommonCiConfig,
42
43    /// Custom GitHub runners, mapped by triple target
44    pub runners: SortedMap<TripleName, GithubRunnerConfig>,
45
46    /// Custom permissions for jobs
47    pub permissions: SortedMap<String, GithubPermissionMap>,
48
49    /// Custom permissions for jobs
50    pub build_setup: Option<String>,
51
52    /// Use these commits for github actions
53    pub action_commits: SortedMap<String, String>,
54}
55
56impl GithubCiConfig {
57    /// Get defaults for the given package
58    pub fn defaults_for_workspace(_workspaces: &WorkspaceGraph, common: &CommonCiConfig) -> Self {
59        Self {
60            common: common.clone(),
61            runners: Default::default(),
62            permissions: Default::default(),
63            action_commits: Default::default(),
64            build_setup: None,
65        }
66    }
67}
68
69impl ApplyLayer for GithubCiConfig {
70    type Layer = GithubCiLayer;
71    fn apply_layer(
72        &mut self,
73        Self::Layer {
74            common,
75            runners,
76            permissions,
77            build_setup,
78            action_commits,
79        }: Self::Layer,
80    ) {
81        self.common.apply_layer(common);
82
83        let mk_default_github_runner = || GithubRunner::new("ubuntu-22.04".to_owned());
84        self.runners.apply_val(runners.map(|runners| {
85            runners
86                .into_iter()
87                .map(|(target_triple, runner)| {
88                    (
89                        target_triple.clone(),
90                        match runner {
91                            StringLikeOr::StringLike(runner) => {
92                                let host = target_for_github_runner(&runner)
93                                    .map(|t| t.to_owned())
94                                    .unwrap_or_else(|| target_triple.clone());
95                                GithubRunnerConfig {
96                                    host,
97                                    runner,
98                                    container: None,
99                                }
100                            }
101                            StringLikeOr::Val(runner_config) => {
102                                let runner = runner_config
103                                    .runner
104                                    .unwrap_or_else(mk_default_github_runner);
105                                let host = runner_config
106                                    .host
107                                    .or_else(|| {
108                                        target_for_github_runner(&runner).map(|t| t.to_owned())
109                                    })
110                                    .unwrap_or_else(|| {
111                                        // if not specified, then assume the custom github runner is
112                                        // the right platform (host == target)
113                                        target_triple.clone()
114                                    });
115                                let container =
116                                    runner_config.container.map(|container| match container {
117                                        StringLikeOr::StringLike(image_name) => {
118                                            ContainerConfig {
119                                                image: image_name,
120                                                // assume x86_64-unknown-linux-musl if not specified
121                                                host: targets::TARGET_X64_LINUX_MUSL.to_owned(),
122                                                package_manager: None,
123                                            }
124                                        }
125                                        StringLikeOr::Val(container_config) => ContainerConfig {
126                                            image: container_config.image,
127                                            host: container_config.host.unwrap_or_else(|| {
128                                                targets::TARGET_X64_LINUX_MUSL.to_owned()
129                                            }),
130                                            package_manager: container_config.package_manager,
131                                        },
132                                    });
133                                GithubRunnerConfig {
134                                    runner,
135                                    host,
136                                    container,
137                                }
138                            }
139                        },
140                    )
141                })
142                .collect()
143        }));
144        self.permissions.apply_val(permissions);
145        self.build_setup.apply_opt(build_setup);
146        self.action_commits.apply_val(action_commits);
147    }
148}
149impl ApplyLayer for GithubCiLayer {
150    type Layer = GithubCiLayer;
151    fn apply_layer(
152        &mut self,
153        Self::Layer {
154            common,
155            runners,
156            permissions,
157            build_setup,
158            action_commits,
159        }: Self::Layer,
160    ) {
161        self.common.apply_layer(common);
162        self.runners.apply_opt(runners);
163        self.permissions.apply_opt(permissions);
164        self.build_setup.apply_opt(build_setup);
165        self.action_commits.apply_opt(action_commits);
166    }
167}
168
169impl std::ops::Deref for GithubCiConfig {
170    type Target = CommonCiConfig;
171    fn deref(&self) -> &Self::Target {
172        &self.common
173    }
174}