├── .github
└── workflows
│ ├── autofix.yml
│ └── ci.yml
├── .gitignore
├── .prettierrc
├── .release-plz.toml
├── .rustfmt.toml
├── .schema
└── latest.json
├── .vscode
└── settings.json
├── CHANGELOG.md
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── README.md
├── crates
├── gh-workflow-macros
│ ├── CHANGELOG.md
│ ├── Cargo.lock
│ ├── Cargo.toml
│ └── src
│ │ └── lib.rs
├── gh-workflow-tailcall
│ ├── CHANGELOG.md
│ ├── Cargo.toml
│ ├── src
│ │ ├── lib.rs
│ │ └── standard.rs
│ └── tests
│ │ └── ci.rs
└── gh-workflow
│ ├── CHANGELOG.md
│ ├── Cargo.toml
│ ├── src
│ ├── cargo.rs
│ ├── comment.yml
│ ├── ctx.rs
│ ├── error.rs
│ ├── event.rs
│ ├── generate.rs
│ ├── lib.rs
│ ├── release_plz.rs
│ ├── rust_flag.rs
│ ├── snapshots
│ │ ├── gh_workflow__generate__tests__add_needs_job.snap
│ │ └── gh_workflow__generate__tests__missing_add_job.snap
│ ├── toolchain.rs
│ └── workflow.rs
│ └── tests
│ ├── fixtures
│ ├── workflow-bench.yml
│ ├── workflow-ci.yml
│ ├── workflow-demo.yml
│ └── workflow-rust.yml
│ └── test-workflow.rs
└── renovate.json
/.github/workflows/autofix.yml:
--------------------------------------------------------------------------------
1 | # -------------------------------------------------------------------
2 | # ------------------------------- WARNING ---------------------------
3 | # -------------------------------------------------------------------
4 | #
5 | # This file was automatically generated by gh-workflows using the
6 | # gh-workflow-gen bin. You should add and commit this file to your
7 | # git repository. **DO NOT EDIT THIS FILE BY HAND!** Any manual changes
8 | # will be lost if the file is regenerated.
9 | #
10 | # To make modifications, update your `build.rs` configuration to adjust
11 | # the workflow description as needed, then regenerate this file to apply
12 | # those changes.
13 | #
14 | # -------------------------------------------------------------------
15 | # ----------------------------- END WARNING -------------------------
16 | # -------------------------------------------------------------------
17 |
18 | name: autofix.ci
19 | env:
20 | RUSTFLAGS: -Dwarnings
21 | on:
22 | pull_request:
23 | types:
24 | - opened
25 | - synchronize
26 | - reopened
27 | branches:
28 | - main
29 | push:
30 | branches:
31 | - main
32 | tags:
33 | - v*
34 | jobs:
35 | lint:
36 | name: Lint Fix
37 | runs-on: ubuntu-latest
38 | permissions:
39 | contents: read
40 | steps:
41 | - name: Checkout Code
42 | uses: actions/checkout@v4
43 | - name: Setup Rust Toolchain
44 | uses: actions-rust-lang/setup-rust-toolchain@v1
45 | with:
46 | toolchain: nightly
47 | components: clippy, rustfmt
48 | cache: true
49 | cache-directories: |-
50 | ~/.cargo/registry
51 | ~/.cargo/git
52 | target
53 | - name: Cargo Fmt
54 | run: cargo +nightly fmt --all
55 | - name: Cargo Clippy
56 | run: cargo +nightly clippy --fix --allow-dirty --all-features --workspace -- -D warnings
57 | - uses: autofix-ci/action@551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef
58 | concurrency:
59 | group: autofix-${{github.ref}}
60 | cancel-in-progress: false
61 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | # -------------------------------------------------------------------
2 | # ------------------------------- WARNING ---------------------------
3 | # -------------------------------------------------------------------
4 | #
5 | # This file was automatically generated by gh-workflows using the
6 | # gh-workflow-gen bin. You should add and commit this file to your
7 | # git repository. **DO NOT EDIT THIS FILE BY HAND!** Any manual changes
8 | # will be lost if the file is regenerated.
9 | #
10 | # To make modifications, update your `build.rs` configuration to adjust
11 | # the workflow description as needed, then regenerate this file to apply
12 | # those changes.
13 | #
14 | # -------------------------------------------------------------------
15 | # ----------------------------- END WARNING -------------------------
16 | # -------------------------------------------------------------------
17 |
18 | name: ci
19 | env:
20 | RUSTFLAGS: -Dwarnings
21 | on:
22 | pull_request:
23 | types:
24 | - opened
25 | - synchronize
26 | - reopened
27 | branches:
28 | - main
29 | push:
30 | branches:
31 | - main
32 | tags:
33 | - v*
34 | jobs:
35 | build:
36 | name: Build and Test
37 | runs-on: ubuntu-latest
38 | permissions:
39 | contents: read
40 | steps:
41 | - name: Checkout Code
42 | uses: actions/checkout@v4
43 | - name: Setup Rust Toolchain
44 | uses: actions-rust-lang/setup-rust-toolchain@v1
45 | with:
46 | toolchain: stable
47 | - name: Install nextest
48 | run: cargo install cargo-nextest --locked
49 | - name: Cargo Nextest
50 | run: cargo nextest run --all-features --workspace
51 | lint:
52 | name: Lint
53 | runs-on: ubuntu-latest
54 | permissions:
55 | contents: read
56 | steps:
57 | - name: Checkout Code
58 | uses: actions/checkout@v4
59 | - name: Setup Rust Toolchain
60 | uses: actions-rust-lang/setup-rust-toolchain@v1
61 | with:
62 | toolchain: nightly
63 | components: clippy, rustfmt
64 | cache: true
65 | cache-directories: |-
66 | ~/.cargo/registry
67 | ~/.cargo/git
68 | target
69 | - name: Cargo Fmt
70 | run: cargo +nightly fmt --all --check
71 | - name: Cargo Clippy
72 | run: cargo +nightly clippy --all-features --workspace -- -D warnings
73 | release:
74 | needs:
75 | - build
76 | - lint
77 | if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }}
78 | name: Release
79 | runs-on: ubuntu-latest
80 | permissions:
81 | contents: write
82 | pull-requests: write
83 | packages: write
84 | env:
85 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
86 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
87 | steps:
88 | - name: Checkout Code
89 | uses: actions/checkout@v4
90 | - name: Release Plz
91 | uses: release-plz/action@v0.5
92 | with:
93 | command: release
94 | concurrency:
95 | group: release-${{github.ref}}
96 | cancel-in-progress: false
97 | release-pr:
98 | needs:
99 | - build
100 | - lint
101 | if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }}
102 | name: Release Pr
103 | runs-on: ubuntu-latest
104 | permissions:
105 | contents: write
106 | pull-requests: write
107 | packages: write
108 | env:
109 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
110 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
111 | steps:
112 | - name: Checkout Code
113 | uses: actions/checkout@v4
114 | - name: Release Plz
115 | uses: release-plz/action@v0.5
116 | with:
117 | command: release-pr
118 | concurrency:
119 | group: release-${{github.ref}}
120 | cancel-in-progress: false
121 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | /**/target/
3 | .forge.*
4 | .env
5 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "bracketSpacing": true
3 | }
4 |
--------------------------------------------------------------------------------
/.release-plz.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | dependencies_update = true
3 | release_always = false
4 |
5 | [[package]]
6 | name = "gh-workflow-macros"
7 | version_group = "core"
8 |
9 | [[package]]
10 | name = "gh-workflow"
11 | version_group = "core"
12 |
--------------------------------------------------------------------------------
/.rustfmt.toml:
--------------------------------------------------------------------------------
1 | unstable_features = true
2 | struct_lit_width = 60
3 | imports_granularity = "Module"
4 | group_imports = "StdExternalCrate"
5 | wrap_comments = true
6 | comment_width = 80
7 |
--------------------------------------------------------------------------------
/.schema/latest.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/draft-07/schema#",
3 | "$id": "https://github.com/release-plz/release-plz/.schema/latest.json",
4 | "title": "Config",
5 | "description": "You can find the documentation of the configuration file [here](https://release-plz.dev/docs/config).",
6 | "type": "object",
7 | "properties": {
8 | "changelog": {
9 | "default": {
10 | "body": null,
11 | "commit_parsers": null,
12 | "commit_preprocessors": null,
13 | "header": null,
14 | "link_parsers": null,
15 | "protect_breaking_commits": null,
16 | "sort_commits": null,
17 | "tag_pattern": null,
18 | "trim": null
19 | },
20 | "allOf": [
21 | {
22 | "$ref": "#/definitions/ChangelogCfg"
23 | }
24 | ]
25 | },
26 | "package": {
27 | "title": "Package",
28 | "description": "Package-specific configuration. This overrides `workspace`. Not all settings of `workspace` can be overridden.",
29 | "default": [],
30 | "type": "array",
31 | "items": {
32 | "$ref": "#/definitions/PackageSpecificConfigWithName"
33 | }
34 | },
35 | "workspace": {
36 | "title": "Workspace",
37 | "description": "Global configuration. Applied to all packages by default.",
38 | "default": {
39 | "allow_dirty": null,
40 | "changelog_config": null,
41 | "changelog_path": null,
42 | "changelog_update": null,
43 | "dependencies_update": null,
44 | "features_always_increment_minor": null,
45 | "git_release_body": null,
46 | "git_release_draft": null,
47 | "git_release_enable": null,
48 | "git_release_latest": null,
49 | "git_release_name": null,
50 | "git_release_type": null,
51 | "git_tag_enable": null,
52 | "git_tag_name": null,
53 | "pr_body": null,
54 | "pr_branch_prefix": null,
55 | "pr_draft": false,
56 | "pr_labels": [],
57 | "pr_name": null,
58 | "publish": null,
59 | "publish_all_features": null,
60 | "publish_allow_dirty": null,
61 | "publish_features": null,
62 | "publish_no_verify": null,
63 | "publish_timeout": null,
64 | "release": null,
65 | "release_always": null,
66 | "release_commits": null,
67 | "repo_url": null,
68 | "semver_check": null
69 | },
70 | "allOf": [
71 | {
72 | "$ref": "#/definitions/Workspace"
73 | }
74 | ]
75 | }
76 | },
77 | "additionalProperties": false,
78 | "definitions": {
79 | "ChangelogCfg": {
80 | "type": "object",
81 | "properties": {
82 | "body": {
83 | "description": "Template that represents a single release in the changelog. It contains the commit messages. This is a [tera](https://keats.github.io/tera/) template.",
84 | "type": [
85 | "string",
86 | "null"
87 | ]
88 | },
89 | "commit_parsers": {
90 | "description": "Commits that don't match any of the commit parsers are skipped.",
91 | "type": [
92 | "array",
93 | "null"
94 | ],
95 | "items": {
96 | "$ref": "#/definitions/CommitParser"
97 | }
98 | },
99 | "commit_preprocessors": {
100 | "description": "An array of commit preprocessors for manipulating the commit messages before parsing/grouping them.",
101 | "type": [
102 | "array",
103 | "null"
104 | ],
105 | "items": {
106 | "$ref": "#/definitions/TextProcessor"
107 | }
108 | },
109 | "header": {
110 | "description": "Text at the beginning of the changelog.",
111 | "type": [
112 | "string",
113 | "null"
114 | ]
115 | },
116 | "link_parsers": {
117 | "description": "An array of link parsers for extracting external references, and turning them into URLs, using regex.",
118 | "type": [
119 | "array",
120 | "null"
121 | ],
122 | "items": {
123 | "$ref": "#/definitions/LinkParser"
124 | }
125 | },
126 | "protect_breaking_commits": {
127 | "description": "Whether to protect all breaking changes from being skipped by a commit parser.",
128 | "type": [
129 | "boolean",
130 | "null"
131 | ]
132 | },
133 | "sort_commits": {
134 | "description": "How to sort the commits inside the various sections.",
135 | "anyOf": [
136 | {
137 | "$ref": "#/definitions/Sorting"
138 | },
139 | {
140 | "type": "null"
141 | }
142 | ]
143 | },
144 | "tag_pattern": {
145 | "description": "A regular expression for matching the git tags to add to the changelog.",
146 | "type": [
147 | "string",
148 | "null"
149 | ]
150 | },
151 | "trim": {
152 | "description": "If set to `true`, leading and trailing whitespace are removed from [`Self::body`].",
153 | "type": [
154 | "boolean",
155 | "null"
156 | ]
157 | }
158 | },
159 | "additionalProperties": false
160 | },
161 | "CommitParser": {
162 | "description": "Parser for grouping commits.",
163 | "type": "object",
164 | "properties": {
165 | "body": {
166 | "description": "Regex for matching the commit body.",
167 | "type": [
168 | "string",
169 | "null"
170 | ]
171 | },
172 | "default_scope": {
173 | "description": "Default scope of the commit.",
174 | "type": [
175 | "string",
176 | "null"
177 | ]
178 | },
179 | "field": {
180 | "description": "Field name of the commit to match the regex against.",
181 | "type": [
182 | "string",
183 | "null"
184 | ]
185 | },
186 | "group": {
187 | "description": "Group of the commit.",
188 | "type": [
189 | "string",
190 | "null"
191 | ]
192 | },
193 | "message": {
194 | "description": "Regex for matching the commit message.",
195 | "type": [
196 | "string",
197 | "null"
198 | ]
199 | },
200 | "pattern": {
201 | "description": "Regex for matching the field value.",
202 | "type": [
203 | "string",
204 | "null"
205 | ]
206 | },
207 | "scope": {
208 | "description": "Commit scope for overriding the default scope.",
209 | "type": [
210 | "string",
211 | "null"
212 | ]
213 | },
214 | "sha": {
215 | "description": "SHA1 of the commit.",
216 | "type": [
217 | "string",
218 | "null"
219 | ]
220 | },
221 | "skip": {
222 | "description": "Whether to skip this commit group.",
223 | "type": [
224 | "boolean",
225 | "null"
226 | ]
227 | }
228 | }
229 | },
230 | "LinkParser": {
231 | "type": "object",
232 | "required": [
233 | "href",
234 | "pattern"
235 | ],
236 | "properties": {
237 | "href": {
238 | "description": "The string used to generate the link URL.",
239 | "type": "string"
240 | },
241 | "pattern": {
242 | "description": "Regex for finding links in the commit message.",
243 | "type": "string"
244 | },
245 | "text": {
246 | "description": "The string used to generate the link text.",
247 | "type": [
248 | "string",
249 | "null"
250 | ]
251 | }
252 | }
253 | },
254 | "PackageSpecificConfigWithName": {
255 | "description": "Config at the `[[package]]` level.",
256 | "type": "object",
257 | "required": [
258 | "name"
259 | ],
260 | "properties": {
261 | "changelog_include": {
262 | "title": "Changelog Include",
263 | "description": "List of package names. Include the changelogs of these packages in the changelog of the current package.",
264 | "type": [
265 | "array",
266 | "null"
267 | ],
268 | "items": {
269 | "type": "string"
270 | }
271 | },
272 | "changelog_path": {
273 | "title": "Changelog Path",
274 | "description": "Normally the changelog is placed in the same directory of the Cargo.toml file. The user can provide a custom path here. `changelog_path` is propagated to the commands: `update`, `release-pr` and `release`.",
275 | "type": [
276 | "string",
277 | "null"
278 | ]
279 | },
280 | "changelog_update": {
281 | "title": "Changelog Update",
282 | "description": "Whether to create/update changelog or not. If unspecified, the changelog is updated.",
283 | "type": [
284 | "boolean",
285 | "null"
286 | ]
287 | },
288 | "features_always_increment_minor": {
289 | "title": "Features Always Increment Minor Version",
290 | "description": "- If `true`, feature commits will always bump the minor version, even in 0.x releases. - If `false` (default), feature commits will only bump the minor version starting with 1.x releases.",
291 | "type": [
292 | "boolean",
293 | "null"
294 | ]
295 | },
296 | "git_release_body": {
297 | "title": "Git Release Body",
298 | "description": "Tera template of the git release body created by release-plz.",
299 | "type": [
300 | "string",
301 | "null"
302 | ]
303 | },
304 | "git_release_draft": {
305 | "title": "Git Release Draft",
306 | "description": "If true, will not auto-publish the release.",
307 | "type": [
308 | "boolean",
309 | "null"
310 | ]
311 | },
312 | "git_release_enable": {
313 | "title": "Git Release Enable",
314 | "description": "Publish the GitHub/Gitea release for the created git tag. Enabled by default.",
315 | "type": [
316 | "boolean",
317 | "null"
318 | ]
319 | },
320 | "git_release_latest": {
321 | "title": "Git Release Latest",
322 | "description": "If true, will set the git release as latest.",
323 | "type": [
324 | "boolean",
325 | "null"
326 | ]
327 | },
328 | "git_release_name": {
329 | "title": "Git Release Name",
330 | "description": "Tera template of the git release name created by release-plz.",
331 | "type": [
332 | "string",
333 | "null"
334 | ]
335 | },
336 | "git_release_type": {
337 | "title": "Git Release Type",
338 | "description": "Whether to mark the created release as not ready for production.",
339 | "anyOf": [
340 | {
341 | "$ref": "#/definitions/ReleaseType"
342 | },
343 | {
344 | "type": "null"
345 | }
346 | ]
347 | },
348 | "git_tag_enable": {
349 | "title": "Git Tag Enable",
350 | "description": "Publish the git tag for the new package version. Enabled by default.",
351 | "type": [
352 | "boolean",
353 | "null"
354 | ]
355 | },
356 | "git_tag_name": {
357 | "title": "Git Tag Name",
358 | "description": "Tera template of the git tag name created by release-plz.",
359 | "type": [
360 | "string",
361 | "null"
362 | ]
363 | },
364 | "name": {
365 | "type": "string"
366 | },
367 | "publish": {
368 | "title": "Publish",
369 | "description": "If `false`, don't run `cargo publish`.",
370 | "type": [
371 | "boolean",
372 | "null"
373 | ]
374 | },
375 | "publish_all_features": {
376 | "title": "Publish All Features",
377 | "description": "If `true`, add the `--all-features` flag to the `cargo publish` command.",
378 | "type": [
379 | "boolean",
380 | "null"
381 | ]
382 | },
383 | "publish_allow_dirty": {
384 | "title": "Publish Allow Dirty",
385 | "description": "If `true`, add the `--allow-dirty` flag to the `cargo publish` command.",
386 | "type": [
387 | "boolean",
388 | "null"
389 | ]
390 | },
391 | "publish_features": {
392 | "title": "Publish Features",
393 | "description": "If `[\"a\", \"b\", \"c\"]`, add the `--features=a,b,c` flag to the `cargo publish` command.",
394 | "type": [
395 | "array",
396 | "null"
397 | ],
398 | "items": {
399 | "type": "string"
400 | }
401 | },
402 | "publish_no_verify": {
403 | "title": "Publish No Verify",
404 | "description": "If `true`, add the `--no-verify` flag to the `cargo publish` command.",
405 | "type": [
406 | "boolean",
407 | "null"
408 | ]
409 | },
410 | "release": {
411 | "title": "Release",
412 | "description": "Used to toggle off the update/release process for a workspace or package.",
413 | "type": [
414 | "boolean",
415 | "null"
416 | ]
417 | },
418 | "semver_check": {
419 | "title": "Semver Check",
420 | "description": "Controls when to run cargo-semver-checks. If unspecified, run cargo-semver-checks if the package is a library.",
421 | "type": [
422 | "boolean",
423 | "null"
424 | ]
425 | },
426 | "version_group": {
427 | "title": "Version group",
428 | "description": "The name of a group of packages that needs to have the same version.",
429 | "type": [
430 | "string",
431 | "null"
432 | ]
433 | }
434 | }
435 | },
436 | "ReleaseType": {
437 | "oneOf": [
438 | {
439 | "title": "Prod",
440 | "description": "Will mark the release as ready for production.",
441 | "type": "string",
442 | "enum": [
443 | "prod"
444 | ]
445 | },
446 | {
447 | "title": "Pre",
448 | "description": "Will mark the release as not ready for production. I.e. as pre-release.",
449 | "type": "string",
450 | "enum": [
451 | "pre"
452 | ]
453 | },
454 | {
455 | "title": "Auto",
456 | "description": "Will mark the release as not ready for production in case there is a semver pre-release in the tag e.g. v1.0.0-rc1. Otherwise, will mark the release as ready for production.",
457 | "type": "string",
458 | "enum": [
459 | "auto"
460 | ]
461 | }
462 | ]
463 | },
464 | "Sorting": {
465 | "type": "string",
466 | "enum": [
467 | "oldest",
468 | "newest"
469 | ]
470 | },
471 | "TextProcessor": {
472 | "description": "Used for modifying commit messages.",
473 | "type": "object",
474 | "required": [
475 | "pattern"
476 | ],
477 | "properties": {
478 | "pattern": {
479 | "description": "Regex for matching a text to replace.",
480 | "type": "string"
481 | },
482 | "replace": {
483 | "description": "Replacement text.",
484 | "type": [
485 | "string",
486 | "null"
487 | ]
488 | },
489 | "replace_command": {
490 | "description": "Command that will be run for replacing the commit message.",
491 | "type": [
492 | "string",
493 | "null"
494 | ]
495 | }
496 | }
497 | },
498 | "Workspace": {
499 | "description": "Config at the `[workspace]` level.",
500 | "type": "object",
501 | "properties": {
502 | "allow_dirty": {
503 | "title": "Allow Dirty",
504 | "description": "- If `true`, allow dirty working directories to be updated. The uncommitted changes will be part of the update. - If `false` or [`Option::None`], the command will fail if the working directory is dirty.",
505 | "type": [
506 | "boolean",
507 | "null"
508 | ]
509 | },
510 | "changelog_config": {
511 | "title": "Changelog Config",
512 | "description": "Path to the git cliff configuration file. Defaults to the `keep a changelog` configuration.",
513 | "type": [
514 | "string",
515 | "null"
516 | ]
517 | },
518 | "changelog_path": {
519 | "title": "Changelog Path",
520 | "description": "Normally the changelog is placed in the same directory of the Cargo.toml file. The user can provide a custom path here. `changelog_path` is propagated to the commands: `update`, `release-pr` and `release`.",
521 | "type": [
522 | "string",
523 | "null"
524 | ]
525 | },
526 | "changelog_update": {
527 | "title": "Changelog Update",
528 | "description": "Whether to create/update changelog or not. If unspecified, the changelog is updated.",
529 | "type": [
530 | "boolean",
531 | "null"
532 | ]
533 | },
534 | "dependencies_update": {
535 | "title": "Dependencies Update",
536 | "description": "- If `true`, update all the dependencies in the Cargo.lock file by running `cargo update`. - If `false` or [`Option::None`], only update the workspace packages by running `cargo update --workspace`.",
537 | "type": [
538 | "boolean",
539 | "null"
540 | ]
541 | },
542 | "features_always_increment_minor": {
543 | "title": "Features Always Increment Minor Version",
544 | "description": "- If `true`, feature commits will always bump the minor version, even in 0.x releases. - If `false` (default), feature commits will only bump the minor version starting with 1.x releases.",
545 | "type": [
546 | "boolean",
547 | "null"
548 | ]
549 | },
550 | "git_release_body": {
551 | "title": "Git Release Body",
552 | "description": "Tera template of the git release body created by release-plz.",
553 | "type": [
554 | "string",
555 | "null"
556 | ]
557 | },
558 | "git_release_draft": {
559 | "title": "Git Release Draft",
560 | "description": "If true, will not auto-publish the release.",
561 | "type": [
562 | "boolean",
563 | "null"
564 | ]
565 | },
566 | "git_release_enable": {
567 | "title": "Git Release Enable",
568 | "description": "Publish the GitHub/Gitea release for the created git tag. Enabled by default.",
569 | "type": [
570 | "boolean",
571 | "null"
572 | ]
573 | },
574 | "git_release_latest": {
575 | "title": "Git Release Latest",
576 | "description": "If true, will set the git release as latest.",
577 | "type": [
578 | "boolean",
579 | "null"
580 | ]
581 | },
582 | "git_release_name": {
583 | "title": "Git Release Name",
584 | "description": "Tera template of the git release name created by release-plz.",
585 | "type": [
586 | "string",
587 | "null"
588 | ]
589 | },
590 | "git_release_type": {
591 | "title": "Git Release Type",
592 | "description": "Whether to mark the created release as not ready for production.",
593 | "anyOf": [
594 | {
595 | "$ref": "#/definitions/ReleaseType"
596 | },
597 | {
598 | "type": "null"
599 | }
600 | ]
601 | },
602 | "git_tag_enable": {
603 | "title": "Git Tag Enable",
604 | "description": "Publish the git tag for the new package version. Enabled by default.",
605 | "type": [
606 | "boolean",
607 | "null"
608 | ]
609 | },
610 | "git_tag_name": {
611 | "title": "Git Tag Name",
612 | "description": "Tera template of the git tag name created by release-plz.",
613 | "type": [
614 | "string",
615 | "null"
616 | ]
617 | },
618 | "pr_body": {
619 | "title": "PR Body",
620 | "description": "Tera template of the pull request's body created by release-plz.",
621 | "type": [
622 | "string",
623 | "null"
624 | ]
625 | },
626 | "pr_branch_prefix": {
627 | "title": "PR Branch Prefix",
628 | "description": "Prefix for the PR Branch",
629 | "type": [
630 | "string",
631 | "null"
632 | ]
633 | },
634 | "pr_draft": {
635 | "title": "PR Draft",
636 | "description": "If `true`, the created release PR will be marked as a draft.",
637 | "default": false,
638 | "type": "boolean"
639 | },
640 | "pr_labels": {
641 | "title": "PR Labels",
642 | "description": "Labels to add to the release PR.",
643 | "default": [],
644 | "type": "array",
645 | "items": {
646 | "type": "string"
647 | }
648 | },
649 | "pr_name": {
650 | "title": "PR Name",
651 | "description": "Tera template of the pull request's name created by release-plz.",
652 | "type": [
653 | "string",
654 | "null"
655 | ]
656 | },
657 | "publish": {
658 | "title": "Publish",
659 | "description": "If `false`, don't run `cargo publish`.",
660 | "type": [
661 | "boolean",
662 | "null"
663 | ]
664 | },
665 | "publish_all_features": {
666 | "title": "Publish All Features",
667 | "description": "If `true`, add the `--all-features` flag to the `cargo publish` command.",
668 | "type": [
669 | "boolean",
670 | "null"
671 | ]
672 | },
673 | "publish_allow_dirty": {
674 | "title": "Publish Allow Dirty",
675 | "description": "If `true`, add the `--allow-dirty` flag to the `cargo publish` command.",
676 | "type": [
677 | "boolean",
678 | "null"
679 | ]
680 | },
681 | "publish_features": {
682 | "title": "Publish Features",
683 | "description": "If `[\"a\", \"b\", \"c\"]`, add the `--features=a,b,c` flag to the `cargo publish` command.",
684 | "type": [
685 | "array",
686 | "null"
687 | ],
688 | "items": {
689 | "type": "string"
690 | }
691 | },
692 | "publish_no_verify": {
693 | "title": "Publish No Verify",
694 | "description": "If `true`, add the `--no-verify` flag to the `cargo publish` command.",
695 | "type": [
696 | "boolean",
697 | "null"
698 | ]
699 | },
700 | "publish_timeout": {
701 | "title": "Publish Timeout",
702 | "description": "Timeout for the publishing process",
703 | "type": [
704 | "string",
705 | "null"
706 | ]
707 | },
708 | "release": {
709 | "title": "Release",
710 | "description": "Used to toggle off the update/release process for a workspace or package.",
711 | "type": [
712 | "boolean",
713 | "null"
714 | ]
715 | },
716 | "release_always": {
717 | "title": "Release always",
718 | "description": "- If true, release-plz release will try to release your packages every time you run it (e.g. on every commit in the main branch). *(Default)*. - If false, `release-plz release` will try release your packages only when you merge the release pr. Use this if you want to commit your packages and publish them later. To determine if a pr is a release-pr, release-plz will check if the branch of the PR starts with `release-plz-`. So if you want to create a PR that should trigger a release (e.g. when you fix the CI), use this branch name format (e.g. `release-plz-fix-ci`).",
719 | "type": [
720 | "boolean",
721 | "null"
722 | ]
723 | },
724 | "release_commits": {
725 | "title": "Release Commits",
726 | "description": "Prepare release only if at least one commit respects this regex.",
727 | "type": [
728 | "string",
729 | "null"
730 | ]
731 | },
732 | "repo_url": {
733 | "title": "Repo URL",
734 | "description": "GitHub/Gitea repository url where your project is hosted. It is used to generate the changelog release link. It defaults to the url of the default remote.",
735 | "type": [
736 | "string",
737 | "null"
738 | ],
739 | "format": "uri"
740 | },
741 | "semver_check": {
742 | "title": "Semver Check",
743 | "description": "Controls when to run cargo-semver-checks. If unspecified, run cargo-semver-checks if the package is a library.",
744 | "type": [
745 | "boolean",
746 | "null"
747 | ]
748 | }
749 | }
750 | }
751 | }
752 | }
753 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cSpell.words": [
3 | "Awarnings",
4 | "Gollum",
5 | "quicktype",
6 | "rustfmt"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [0.5.0](https://github.com/tailcallhq/gh-workflow/compare/v0.4.1...v0.5.0) - 2024-11-28
9 |
10 | ### Other
11 |
12 | - fix workflow name
13 |
14 | ## [0.4.1](https://github.com/tailcallhq/rust-gh-workflow/compare/gh-workflow-v0.4.0...gh-workflow-v0.4.1) - 2024-11-16
15 |
16 | ### Fixed
17 |
18 | - error when `.github` dir does not exist ([#51](https://github.com/tailcallhq/rust-gh-workflow/pull/51))
19 |
20 | ## [0.4.0](https://github.com/tailcallhq/rust-gh-workflow/compare/gh-workflow-v0.3.0...gh-workflow-v0.4.0) - 2024-11-13
21 |
22 | ### Other
23 |
24 | - lint fixes
25 |
26 | ## [0.3.0](https://github.com/tailcallhq/rust-gh-workflow/compare/gh-workflow-v0.2.1...gh-workflow-v0.3.0) - 2024-11-11
27 |
28 | ### Other
29 |
30 | - update workflow
31 |
32 | ## v0.2.0 (2024-11-11)
33 |
34 |
35 |
36 |
37 |
38 | ### Chore
39 |
40 | - update build.rs using `Generate` and custom name
41 | - impl `Step::working_directory`
42 |
43 | ### New Features
44 |
45 | - add `add_with` operator` on StepValue
46 | - add Setters for Event
47 | - Make generate public fixes #26
48 |
49 | ### Bug Fixes
50 |
51 | - `Job::runs_on`
52 | - add names to default Rust workflow
53 | - Improve type-safety for Step
54 |
55 | ### Refactor
56 |
57 | - many many changes
58 |
59 | ### Commit Statistics
60 |
61 |
62 |
63 | - 1 commit contributed to the release.
64 | - 1 commit was understood as [conventional](https://www.conventionalcommits.org).
65 | - 0 issues like '(#ID)' were seen in commit messages
66 |
67 | ### Commit Details
68 |
69 |
70 |
71 | view details
72 |
73 | * **Uncategorized**
74 | - Improve type-safety for Step ([`790765a`](https://github.com/tailcallhq/rust-gh-workflow/commit/790765acf303891b491a37ee7d07413debd90f67))
75 |
76 |
77 | ## v0.1.2 (2024-11-08)
78 |
79 |
80 |
81 | ### Chore
82 |
83 | - lint fixes
84 |
85 | ### New Features
86 |
87 | - add `Workflow::setup_rust()` helper
88 |
89 | ### Bug Fixes
90 |
91 | - add wasm to possible targets
92 |
93 | ### Commit Statistics
94 |
95 |
96 |
97 | - 4 commits contributed to the release.
98 | - 3 commits were understood as [conventional](https://www.conventionalcommits.org).
99 | - 0 issues like '(#ID)' were seen in commit messages
100 |
101 | ### Commit Details
102 |
103 |
104 |
105 | view details
106 |
107 | * **Uncategorized**
108 | - Release gh-workflow v0.1.2 ([`e71bec6`](https://github.com/tailcallhq/rust-gh-workflow/commit/e71bec6475696c55f7db6cb399fe1572bde5d017))
109 | - Lint fixes ([`9230d1f`](https://github.com/tailcallhq/rust-gh-workflow/commit/9230d1f1dc00b87038ec17f39deca77c9be6ffa6))
110 | - Add `Workflow::setup_rust()` helper ([`5a3f184`](https://github.com/tailcallhq/rust-gh-workflow/commit/5a3f18477a2bddc662d3f100e7dd6cbf002cdd2f))
111 | - Add wasm to possible targets ([`f74da3d`](https://github.com/tailcallhq/rust-gh-workflow/commit/f74da3df992ee7c10564679c10b695e5b96a85c6))
112 |
113 |
114 | ## v0.1.1 (2024-11-08)
115 |
116 | ### Bug Fixes
117 |
118 | - add readme file
119 |
120 | ### Commit Statistics
121 |
122 |
123 |
124 | - 4 commits contributed to the release.
125 | - 1 commit was understood as [conventional](https://www.conventionalcommits.org).
126 | - 0 issues like '(#ID)' were seen in commit messages
127 |
128 | ### Commit Details
129 |
130 |
131 |
132 | view details
133 |
134 | * **Uncategorized**
135 | - Release gh-workflow v0.1.1 ([`4dfbd11`](https://github.com/tailcallhq/rust-gh-workflow/commit/4dfbd11bb17f22245601c7a1d36d701328e8e646))
136 | - Release gh-workflow v0.1.1 ([`c58445e`](https://github.com/tailcallhq/rust-gh-workflow/commit/c58445effa55bca60e2283205feba758365efe51))
137 | - Release gh-workflow v0.1.1 ([`677a89e`](https://github.com/tailcallhq/rust-gh-workflow/commit/677a89e38a74410db14c7546499a1ce818befd96))
138 | - Add readme file ([`55d81b0`](https://github.com/tailcallhq/rust-gh-workflow/commit/55d81b06bf673774e9559915cbe1cb49ccf0a6c5))
139 |
140 |
141 | ## v0.1.0 (2024-11-08)
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | ### Chore
154 |
155 | - update license
156 | - add license
157 | - update build
158 | - accept path `AsRef`
159 | - add warning in generated config
160 | - autogen CI
161 | - update folder structure
162 |
163 | ### Chore
164 |
165 | - update license
166 |
167 | ### Chore
168 |
169 | - add changelog
170 |
171 | ### New Features
172 |
173 | - validate on CI
174 | - add events
175 |
176 | ### Bug Fixes
177 |
178 | - tests
179 | * refactor: move tests from `workflow.rs` to tests dir
180 | * remove unused deps
181 | * move fixtures dir
182 | * chore: rename files
183 | * chore: import updates
184 | * chore: update workflows
185 | * chore: update workflow
186 | * fix err on workflow-bench.yml
187 | * partial
188 | * partially fix tests
189 | * fix tests
190 | * drop unused struct
191 | * revert unwanted change in `needs`
192 | * revert unwanted change in `needs`
193 | * drop `build_matrix.yml`
194 | * revert
195 |
196 | ### Commit Statistics
197 |
198 |
199 |
200 | - 18 commits contributed to the release.
201 | - 12 commits were understood as [conventional](https://www.conventionalcommits.org).
202 | - 4 unique issues were worked on: [#13](https://github.com/tailcallhq/rust-gh-workflow/issues/13), [#14](https://github.com/tailcallhq/rust-gh-workflow/issues/14), [#19](https://github.com/tailcallhq/rust-gh-workflow/issues/19), [#21](https://github.com/tailcallhq/rust-gh-workflow/issues/21)
203 |
204 | ### Commit Details
205 |
206 |
207 |
208 | view details
209 |
210 | * **[#13](https://github.com/tailcallhq/rust-gh-workflow/issues/13)**
211 | - Tests ([`e91cd89`](https://github.com/tailcallhq/rust-gh-workflow/commit/e91cd8944cfa9cf758889c4157f12bc01758fee1))
212 | * **[#14](https://github.com/tailcallhq/rust-gh-workflow/issues/14)**
213 | - Autogen CI ([`dccdb36`](https://github.com/tailcallhq/rust-gh-workflow/commit/dccdb3612602559e3c39e83ae3894086e06c5a5d))
214 | * **[#19](https://github.com/tailcallhq/rust-gh-workflow/issues/19)**
215 | - Accept path `AsRef` ([`55f52de`](https://github.com/tailcallhq/rust-gh-workflow/commit/55f52de53065d626aaea8007651251a9a86acc98))
216 | * **[#21](https://github.com/tailcallhq/rust-gh-workflow/issues/21)**
217 | - Validate on CI ([`8f3615d`](https://github.com/tailcallhq/rust-gh-workflow/commit/8f3615d7d3e6b71946b09c68a4ec8dc7cb3418a7))
218 | * **Uncategorized**
219 | - Release gh-workflow v0.1.0 ([`374d65c`](https://github.com/tailcallhq/rust-gh-workflow/commit/374d65c8c638b50efe5724d44f2bc1b409ab5a56))
220 | - Update license ([`17a92e4`](https://github.com/tailcallhq/rust-gh-workflow/commit/17a92e4d66226b5b22feadce6b2b79326be328d1))
221 | - Release gh-workflow v0.1.0 ([`3d5543b`](https://github.com/tailcallhq/rust-gh-workflow/commit/3d5543b427685752770a75ce3d078f7b38f7a5f2))
222 | - Release gh-workflow v0.1.0 ([`4602f22`](https://github.com/tailcallhq/rust-gh-workflow/commit/4602f22c2437cad2467ee083402b0eb7f29ab045))
223 | - Add changelog ([`cbf51ab`](https://github.com/tailcallhq/rust-gh-workflow/commit/cbf51abc82da429539cff463aebb83f941b62922))
224 | - Update license ([`7f8b45f`](https://github.com/tailcallhq/rust-gh-workflow/commit/7f8b45f3f2065fc953da5fd4447183d0bcb94e38))
225 | - Update manifest ([`770b3e3`](https://github.com/tailcallhq/rust-gh-workflow/commit/770b3e33773db936b91a416fb3ac26c809b2ad14))
226 | - Add license ([`d73d9fa`](https://github.com/tailcallhq/rust-gh-workflow/commit/d73d9faf093e15fc9d91a9318ca84f6113a310b0))
227 | - Update build ([`1a004fc`](https://github.com/tailcallhq/rust-gh-workflow/commit/1a004fc27cb6c44a6b76d5ca20b50dbfc90b4efe))
228 | - Update event ([`a0bf957`](https://github.com/tailcallhq/rust-gh-workflow/commit/a0bf95769e66eed96cc9b5b81c51bcf38e1b49fc))
229 | - Drop commented code ([`fe53956`](https://github.com/tailcallhq/rust-gh-workflow/commit/fe539566c65313f19f8773fea6cf78aa49cb7e65))
230 | - Add events ([`d770fc8`](https://github.com/tailcallhq/rust-gh-workflow/commit/d770fc8bec19a8dd6e7b680b8d61819383b50498))
231 | - Add warning in generated config ([`9054532`](https://github.com/tailcallhq/rust-gh-workflow/commit/90545329d44378175e1bbabe5595868720961dad))
232 | - Update folder structure ([`5e43aa1`](https://github.com/tailcallhq/rust-gh-workflow/commit/5e43aa120b9f37227bc0d1e9d2c3c840a652319e))
233 |
234 |
235 |
--------------------------------------------------------------------------------
/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 4
4 |
5 | [[package]]
6 | name = "async-trait"
7 | version = "0.1.88"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
10 | dependencies = [
11 | "proc-macro2",
12 | "quote",
13 | "syn 2.0.101",
14 | ]
15 |
16 | [[package]]
17 | name = "autocfg"
18 | version = "1.4.0"
19 | source = "registry+https://github.com/rust-lang/crates.io-index"
20 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
21 |
22 | [[package]]
23 | name = "console"
24 | version = "0.15.11"
25 | source = "registry+https://github.com/rust-lang/crates.io-index"
26 | checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8"
27 | dependencies = [
28 | "encode_unicode",
29 | "libc",
30 | "once_cell",
31 | "windows-sys",
32 | ]
33 |
34 | [[package]]
35 | name = "darling"
36 | version = "0.20.11"
37 | source = "registry+https://github.com/rust-lang/crates.io-index"
38 | checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
39 | dependencies = [
40 | "darling_core",
41 | "darling_macro",
42 | ]
43 |
44 | [[package]]
45 | name = "darling_core"
46 | version = "0.20.11"
47 | source = "registry+https://github.com/rust-lang/crates.io-index"
48 | checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
49 | dependencies = [
50 | "fnv",
51 | "ident_case",
52 | "proc-macro2",
53 | "quote",
54 | "strsim",
55 | "syn 2.0.101",
56 | ]
57 |
58 | [[package]]
59 | name = "darling_macro"
60 | version = "0.20.11"
61 | source = "registry+https://github.com/rust-lang/crates.io-index"
62 | checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
63 | dependencies = [
64 | "darling_core",
65 | "quote",
66 | "syn 2.0.101",
67 | ]
68 |
69 | [[package]]
70 | name = "derive_more"
71 | version = "2.0.1"
72 | source = "registry+https://github.com/rust-lang/crates.io-index"
73 | checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
74 | dependencies = [
75 | "derive_more-impl",
76 | ]
77 |
78 | [[package]]
79 | name = "derive_more-impl"
80 | version = "2.0.1"
81 | source = "registry+https://github.com/rust-lang/crates.io-index"
82 | checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
83 | dependencies = [
84 | "proc-macro2",
85 | "quote",
86 | "syn 2.0.101",
87 | ]
88 |
89 | [[package]]
90 | name = "derive_setters"
91 | version = "0.1.7"
92 | source = "registry+https://github.com/rust-lang/crates.io-index"
93 | checksum = "d9c848e86c87e5cc305313041c5677d4d95d60baa71cf95e5f6ea2554bb629ff"
94 | dependencies = [
95 | "darling",
96 | "proc-macro2",
97 | "quote",
98 | "syn 2.0.101",
99 | ]
100 |
101 | [[package]]
102 | name = "diff"
103 | version = "0.1.13"
104 | source = "registry+https://github.com/rust-lang/crates.io-index"
105 | checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
106 |
107 | [[package]]
108 | name = "encode_unicode"
109 | version = "1.0.0"
110 | source = "registry+https://github.com/rust-lang/crates.io-index"
111 | checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
112 |
113 | [[package]]
114 | name = "equivalent"
115 | version = "1.0.2"
116 | source = "registry+https://github.com/rust-lang/crates.io-index"
117 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
118 |
119 | [[package]]
120 | name = "fnv"
121 | version = "1.0.7"
122 | source = "registry+https://github.com/rust-lang/crates.io-index"
123 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
124 |
125 | [[package]]
126 | name = "gh-workflow"
127 | version = "0.6.0"
128 | dependencies = [
129 | "async-trait",
130 | "derive_more",
131 | "derive_setters",
132 | "gh-workflow-macros",
133 | "indexmap",
134 | "insta",
135 | "merge",
136 | "pretty_assertions",
137 | "serde",
138 | "serde_json",
139 | "serde_yaml",
140 | "strum_macros",
141 | ]
142 |
143 | [[package]]
144 | name = "gh-workflow-macros"
145 | version = "0.6.0"
146 | dependencies = [
147 | "heck",
148 | "quote",
149 | "syn 2.0.101",
150 | ]
151 |
152 | [[package]]
153 | name = "gh-workflow-tailcall"
154 | version = "0.5.2"
155 | dependencies = [
156 | "derive_setters",
157 | "gh-workflow",
158 | "heck",
159 | "insta",
160 | "pretty_assertions",
161 | ]
162 |
163 | [[package]]
164 | name = "hashbrown"
165 | version = "0.15.3"
166 | source = "registry+https://github.com/rust-lang/crates.io-index"
167 | checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
168 |
169 | [[package]]
170 | name = "heck"
171 | version = "0.5.0"
172 | source = "registry+https://github.com/rust-lang/crates.io-index"
173 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
174 |
175 | [[package]]
176 | name = "ident_case"
177 | version = "1.0.1"
178 | source = "registry+https://github.com/rust-lang/crates.io-index"
179 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
180 |
181 | [[package]]
182 | name = "indexmap"
183 | version = "2.9.0"
184 | source = "registry+https://github.com/rust-lang/crates.io-index"
185 | checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
186 | dependencies = [
187 | "equivalent",
188 | "hashbrown",
189 | "serde",
190 | ]
191 |
192 | [[package]]
193 | name = "insta"
194 | version = "1.43.1"
195 | source = "registry+https://github.com/rust-lang/crates.io-index"
196 | checksum = "154934ea70c58054b556dd430b99a98c2a7ff5309ac9891597e339b5c28f4371"
197 | dependencies = [
198 | "console",
199 | "once_cell",
200 | "similar",
201 | ]
202 |
203 | [[package]]
204 | name = "itoa"
205 | version = "1.0.15"
206 | source = "registry+https://github.com/rust-lang/crates.io-index"
207 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
208 |
209 | [[package]]
210 | name = "libc"
211 | version = "0.2.172"
212 | source = "registry+https://github.com/rust-lang/crates.io-index"
213 | checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
214 |
215 | [[package]]
216 | name = "memchr"
217 | version = "2.7.4"
218 | source = "registry+https://github.com/rust-lang/crates.io-index"
219 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
220 |
221 | [[package]]
222 | name = "merge"
223 | version = "0.1.0"
224 | source = "registry+https://github.com/rust-lang/crates.io-index"
225 | checksum = "10bbef93abb1da61525bbc45eeaff6473a41907d19f8f9aa5168d214e10693e9"
226 | dependencies = [
227 | "merge_derive",
228 | "num-traits",
229 | ]
230 |
231 | [[package]]
232 | name = "merge_derive"
233 | version = "0.1.0"
234 | source = "registry+https://github.com/rust-lang/crates.io-index"
235 | checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07"
236 | dependencies = [
237 | "proc-macro-error",
238 | "proc-macro2",
239 | "quote",
240 | "syn 1.0.109",
241 | ]
242 |
243 | [[package]]
244 | name = "num-traits"
245 | version = "0.2.19"
246 | source = "registry+https://github.com/rust-lang/crates.io-index"
247 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
248 | dependencies = [
249 | "autocfg",
250 | ]
251 |
252 | [[package]]
253 | name = "once_cell"
254 | version = "1.21.3"
255 | source = "registry+https://github.com/rust-lang/crates.io-index"
256 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
257 |
258 | [[package]]
259 | name = "pretty_assertions"
260 | version = "1.4.1"
261 | source = "registry+https://github.com/rust-lang/crates.io-index"
262 | checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
263 | dependencies = [
264 | "diff",
265 | "yansi",
266 | ]
267 |
268 | [[package]]
269 | name = "proc-macro-error"
270 | version = "1.0.4"
271 | source = "registry+https://github.com/rust-lang/crates.io-index"
272 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
273 | dependencies = [
274 | "proc-macro-error-attr",
275 | "proc-macro2",
276 | "quote",
277 | "syn 1.0.109",
278 | "version_check",
279 | ]
280 |
281 | [[package]]
282 | name = "proc-macro-error-attr"
283 | version = "1.0.4"
284 | source = "registry+https://github.com/rust-lang/crates.io-index"
285 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
286 | dependencies = [
287 | "proc-macro2",
288 | "quote",
289 | "version_check",
290 | ]
291 |
292 | [[package]]
293 | name = "proc-macro2"
294 | version = "1.0.95"
295 | source = "registry+https://github.com/rust-lang/crates.io-index"
296 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
297 | dependencies = [
298 | "unicode-ident",
299 | ]
300 |
301 | [[package]]
302 | name = "quote"
303 | version = "1.0.40"
304 | source = "registry+https://github.com/rust-lang/crates.io-index"
305 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
306 | dependencies = [
307 | "proc-macro2",
308 | ]
309 |
310 | [[package]]
311 | name = "rustversion"
312 | version = "1.0.20"
313 | source = "registry+https://github.com/rust-lang/crates.io-index"
314 | checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
315 |
316 | [[package]]
317 | name = "ryu"
318 | version = "1.0.20"
319 | source = "registry+https://github.com/rust-lang/crates.io-index"
320 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
321 |
322 | [[package]]
323 | name = "serde"
324 | version = "1.0.219"
325 | source = "registry+https://github.com/rust-lang/crates.io-index"
326 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
327 | dependencies = [
328 | "serde_derive",
329 | ]
330 |
331 | [[package]]
332 | name = "serde_derive"
333 | version = "1.0.219"
334 | source = "registry+https://github.com/rust-lang/crates.io-index"
335 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
336 | dependencies = [
337 | "proc-macro2",
338 | "quote",
339 | "syn 2.0.101",
340 | ]
341 |
342 | [[package]]
343 | name = "serde_json"
344 | version = "1.0.140"
345 | source = "registry+https://github.com/rust-lang/crates.io-index"
346 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
347 | dependencies = [
348 | "itoa",
349 | "memchr",
350 | "ryu",
351 | "serde",
352 | ]
353 |
354 | [[package]]
355 | name = "serde_yaml"
356 | version = "0.9.34+deprecated"
357 | source = "registry+https://github.com/rust-lang/crates.io-index"
358 | checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
359 | dependencies = [
360 | "indexmap",
361 | "itoa",
362 | "ryu",
363 | "serde",
364 | "unsafe-libyaml",
365 | ]
366 |
367 | [[package]]
368 | name = "similar"
369 | version = "2.7.0"
370 | source = "registry+https://github.com/rust-lang/crates.io-index"
371 | checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
372 |
373 | [[package]]
374 | name = "strsim"
375 | version = "0.11.1"
376 | source = "registry+https://github.com/rust-lang/crates.io-index"
377 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
378 |
379 | [[package]]
380 | name = "strum_macros"
381 | version = "0.27.1"
382 | source = "registry+https://github.com/rust-lang/crates.io-index"
383 | checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8"
384 | dependencies = [
385 | "heck",
386 | "proc-macro2",
387 | "quote",
388 | "rustversion",
389 | "syn 2.0.101",
390 | ]
391 |
392 | [[package]]
393 | name = "syn"
394 | version = "1.0.109"
395 | source = "registry+https://github.com/rust-lang/crates.io-index"
396 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
397 | dependencies = [
398 | "proc-macro2",
399 | "quote",
400 | "unicode-ident",
401 | ]
402 |
403 | [[package]]
404 | name = "syn"
405 | version = "2.0.101"
406 | source = "registry+https://github.com/rust-lang/crates.io-index"
407 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
408 | dependencies = [
409 | "proc-macro2",
410 | "quote",
411 | "unicode-ident",
412 | ]
413 |
414 | [[package]]
415 | name = "unicode-ident"
416 | version = "1.0.18"
417 | source = "registry+https://github.com/rust-lang/crates.io-index"
418 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
419 |
420 | [[package]]
421 | name = "unsafe-libyaml"
422 | version = "0.2.11"
423 | source = "registry+https://github.com/rust-lang/crates.io-index"
424 | checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
425 |
426 | [[package]]
427 | name = "version_check"
428 | version = "0.9.5"
429 | source = "registry+https://github.com/rust-lang/crates.io-index"
430 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
431 |
432 | [[package]]
433 | name = "windows-sys"
434 | version = "0.59.0"
435 | source = "registry+https://github.com/rust-lang/crates.io-index"
436 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
437 | dependencies = [
438 | "windows-targets",
439 | ]
440 |
441 | [[package]]
442 | name = "windows-targets"
443 | version = "0.52.6"
444 | source = "registry+https://github.com/rust-lang/crates.io-index"
445 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
446 | dependencies = [
447 | "windows_aarch64_gnullvm",
448 | "windows_aarch64_msvc",
449 | "windows_i686_gnu",
450 | "windows_i686_gnullvm",
451 | "windows_i686_msvc",
452 | "windows_x86_64_gnu",
453 | "windows_x86_64_gnullvm",
454 | "windows_x86_64_msvc",
455 | ]
456 |
457 | [[package]]
458 | name = "windows_aarch64_gnullvm"
459 | version = "0.52.6"
460 | source = "registry+https://github.com/rust-lang/crates.io-index"
461 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
462 |
463 | [[package]]
464 | name = "windows_aarch64_msvc"
465 | version = "0.52.6"
466 | source = "registry+https://github.com/rust-lang/crates.io-index"
467 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
468 |
469 | [[package]]
470 | name = "windows_i686_gnu"
471 | version = "0.52.6"
472 | source = "registry+https://github.com/rust-lang/crates.io-index"
473 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
474 |
475 | [[package]]
476 | name = "windows_i686_gnullvm"
477 | version = "0.52.6"
478 | source = "registry+https://github.com/rust-lang/crates.io-index"
479 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
480 |
481 | [[package]]
482 | name = "windows_i686_msvc"
483 | version = "0.52.6"
484 | source = "registry+https://github.com/rust-lang/crates.io-index"
485 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
486 |
487 | [[package]]
488 | name = "windows_x86_64_gnu"
489 | version = "0.52.6"
490 | source = "registry+https://github.com/rust-lang/crates.io-index"
491 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
492 |
493 | [[package]]
494 | name = "windows_x86_64_gnullvm"
495 | version = "0.52.6"
496 | source = "registry+https://github.com/rust-lang/crates.io-index"
497 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
498 |
499 | [[package]]
500 | name = "windows_x86_64_msvc"
501 | version = "0.52.6"
502 | source = "registry+https://github.com/rust-lang/crates.io-index"
503 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
504 |
505 | [[package]]
506 | name = "yansi"
507 | version = "1.0.1"
508 | source = "registry+https://github.com/rust-lang/crates.io-index"
509 | checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
510 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | resolver = "2"
3 | members = ["crates/*"]
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2023 Tailcall
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🦀 Rust GitHub Actions Workflow 🚀
2 |
3 | [](https://www.rust-lang.org)
4 | [](https://github.com/tailcallhq/rust-gh-workflow/actions)
5 | [](https://opensource.org/licenses/MIT)
6 | [](https://crates.io/crates/gh-workflow)
7 | [](https://github.com/tailcallhq/rust-gh-workflow/graphs/contributors)
8 | [](https://github.com/tailcallhq/rust-gh-workflow/network/members)
9 | [](https://github.com/tailcallhq/rust-gh-workflow/stargazers)
10 | [](https://github.com/tailcallhq/rust-gh-workflow/issues)
11 |
12 | ## 🧑💻 What is Rust GitHub Workflows?
13 |
14 | **Rust GitHub Workflows** is a library that allows developers to write GitHub Actions in Rust. It empowers you to automate, manage, and improve your CI/CD pipelines in a type-safe manner.
15 |
16 | GitHub Actions is powerful, but writing workflows can sometimes feel repetitive, tricky and frustrating with no strict type-checking. That's where **Rust GitHub Workflows** steps in! 🦾
17 |
18 | - 🔥 **Rust-Powered**: Leverage the type-safety of Rust for writing workflows.
19 | - 📦 **Crate-friendly**: Build reusable workflows and publish them as crates.
20 |
21 | ## 📦 Installation
22 |
23 | To use **Rust GitHub Workflows** in your project, add it to your `Cargo.toml`:
24 |
25 | ```toml
26 | [build-dependencies]
27 | gh-workflow = "*" # Add the latest version
28 | ```
29 |
30 | Then you can start creating GitHub Actions in your [tests/ci.rs](https://github.com/tailcallhq/rust-gh-workflow/blob/main/tests/ci.rs).
31 |
32 | ## 👷 Usage
33 |
34 | - Simply add a `tests/ci.rs` file to your project's tests directory.
35 | - Add the following code to generate the GitHub Actions workflow:
36 |
37 | ```rust
38 | use gh_workflows::*;
39 |
40 | #[test]
41 | fn main() {
42 | // Create a basic workflow
43 | let workflow = Workflow::setup_rust();
44 |
45 | // Generate the ci.yml
46 | workflow.generate().unwrap();
47 | }
48 | ```
49 |
50 | To view a fully functional example, check out the [tests/ci.rs](https://github.com/tailcallhq/gh-workflow/blob/main/crates/gh-workflow-tailcall/tests/ci.rs) of this project.
51 |
52 | - Run `cargo test` to generate the GitHub Actions workflow.
53 |
54 | ## 💡 Why Rust?
55 |
56 | Rust provides the perfect combination of speed, safety, and flexibility, making it an ideal choice for writing GitHub Actions. With Rust, you get strong typing, memory safety, and the ability to reuse existing code, which can make your automation scripts more robust and maintainable.
57 |
58 | ## 📄 License
59 |
60 | This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENSE) file for details.
61 |
62 | ## 🙌 Contributors
63 |
64 | A big thank you to all the contributors who helped make this project a success! 🙏
65 |
66 | [](https://github.com/tailcallhq/rust-gh-workflow/graphs/contributors)
67 |
68 | ## 🌟 Show Your Support
69 |
70 | If you like this project, please consider giving it a ⭐ on [GitHub](https://github.com/tailcallhq/rust-gh-workflow) and share it with the community!
71 |
72 | ## 🔗 Inspiration
73 |
74 | This project was inspired by the following repositories:
75 |
76 | - [sbt/sbt-github-actions](https://github.com/sbt/sbt-github-actions)
77 | - [emmanuelnk/github-actions-workflow-ts](https://github.com/emmanuelnk/github-actions-workflow-ts)
78 |
79 | ---
80 |
81 | Happy automating with Rust! 🦀❤️
82 |
--------------------------------------------------------------------------------
/crates/gh-workflow-macros/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Unreleased]
9 |
--------------------------------------------------------------------------------
/crates/gh-workflow-macros/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 3
4 |
5 | [[package]]
6 | name = "gh-workflow-macros"
7 | version = "0.1.0"
8 | dependencies = [
9 | "heck",
10 | "quote",
11 | "syn",
12 | ]
13 |
14 | [[package]]
15 | name = "heck"
16 | version = "0.5.0"
17 | source = "registry+https://github.com/rust-lang/crates.io-index"
18 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
19 |
20 | [[package]]
21 | name = "proc-macro2"
22 | version = "1.0.92"
23 | source = "registry+https://github.com/rust-lang/crates.io-index"
24 | checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
25 | dependencies = [
26 | "unicode-ident",
27 | ]
28 |
29 | [[package]]
30 | name = "quote"
31 | version = "1.0.37"
32 | source = "registry+https://github.com/rust-lang/crates.io-index"
33 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
34 | dependencies = [
35 | "proc-macro2",
36 | ]
37 |
38 | [[package]]
39 | name = "syn"
40 | version = "2.0.89"
41 | source = "registry+https://github.com/rust-lang/crates.io-index"
42 | checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
43 | dependencies = [
44 | "proc-macro2",
45 | "quote",
46 | "unicode-ident",
47 | ]
48 |
49 | [[package]]
50 | name = "unicode-ident"
51 | version = "1.0.14"
52 | source = "registry+https://github.com/rust-lang/crates.io-index"
53 | checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
54 |
--------------------------------------------------------------------------------
/crates/gh-workflow-macros/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "gh-workflow-macros"
3 | version = "0.6.0"
4 | edition = "2021"
5 |
6 | description = "macros for gh-workflow"
7 | license = "Apache-2.0"
8 | documentation = "https://docs.rs/gh-workflow"
9 | homepage = "https://github.com/tailcallhq/gh-workflow"
10 | repository = "https://github.com/tailcallhq/gh-workflow"
11 | keywords = ["github", "actions", "workflow", "generator"]
12 |
13 | [lib]
14 | proc-macro = true
15 |
16 | [dependencies]
17 | syn = "2.0"
18 | quote = "1.0"
19 | heck = "0.5.0"
20 |
--------------------------------------------------------------------------------
/crates/gh-workflow-macros/src/lib.rs:
--------------------------------------------------------------------------------
1 | use heck::ToSnakeCase;
2 | use proc_macro::TokenStream;
3 | use quote::quote;
4 | use syn::{parse_macro_input, Data, DeriveInput, Fields};
5 |
6 | #[proc_macro_derive(Context)]
7 | pub fn derive_expr(input: TokenStream) -> TokenStream {
8 | let input = parse_macro_input!(input as DeriveInput);
9 | let struct_name = input.ident;
10 | let ctor_name = struct_name.to_string().to_snake_case();
11 | let ctor_id = syn::Ident::new(&ctor_name, struct_name.span());
12 |
13 | // Ensure it's a struct and get its fields
14 | let fields = if let Data::Struct(data_struct) = input.data {
15 | if let Fields::Named(fields) = data_struct.fields {
16 | fields
17 | } else {
18 | panic!("#[derive(Context)] only supports structs with named fields")
19 | }
20 | } else {
21 | panic!("#[derive(Context)] can only be used with structs");
22 | };
23 |
24 | // Generate methods for each field
25 | let methods = fields.named.iter().map(|field| {
26 | let field_name = &field.ident;
27 | let field_type = &field.ty;
28 | let field_name_str = field_name.as_ref().unwrap().to_string();
29 | quote! {
30 | pub fn #field_name(&self) -> Context<#field_type> {
31 | self.select::<#field_type>(#field_name_str)
32 | }
33 | }
34 | });
35 |
36 | // Generate the output code
37 | let expanded = quote! {
38 | impl Context<#struct_name> {
39 | #(#methods)*
40 |
41 | pub fn #ctor_id() -> Self {
42 | Context::::new().select(stringify!(#ctor_name))
43 | }
44 | }
45 | };
46 |
47 | // eprintln!("Generated code:\n{}", expanded);
48 |
49 | TokenStream::from(expanded)
50 | }
51 |
--------------------------------------------------------------------------------
/crates/gh-workflow-tailcall/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Unreleased]
9 |
10 | ## [0.5.2](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-tailcall-v0.5.1...gh-workflow-tailcall-v0.5.2) - 2025-05-06
11 |
12 | ### Added
13 |
14 | - *(event)* add tags filter to Push struct for event handling ([#157](https://github.com/tailcallhq/gh-workflow/pull/157))
15 |
16 | ## [0.5.1](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-tailcall-v0.5.0...gh-workflow-tailcall-v0.5.1) - 2025-01-29
17 |
18 | ### Other
19 |
20 | - updated the following local packages: gh-workflow
21 |
22 | ## [0.5.0](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-tailcall-v0.4.1...gh-workflow-tailcall-v0.5.0) - 2025-01-19
23 |
24 | ### Fixed
25 |
26 | - correct cargo install command in CI workflow and standard workflow
27 |
28 | ## [0.4.1](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-tailcall-v0.4.0...gh-workflow-tailcall-v0.4.1) - 2025-01-13
29 |
30 | ### Added
31 |
32 | - add caching support for Cargo toolchain in CI workflows
33 |
34 | ## [0.4.0](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-tailcall-v0.3.0...gh-workflow-tailcall-v0.4.0) - 2025-01-13
35 |
36 | ### Fixed
37 |
38 | - update autofix-ci/action version in workflow files
39 |
40 | ## [0.3.0](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-tailcall-v0.2.1...gh-workflow-tailcall-v0.3.0) - 2025-01-13
41 |
42 | ### Added
43 |
44 | - add setup steps to Workflow for job initialization
45 |
46 | ## [0.2.1](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-tailcall-v0.2.0...gh-workflow-tailcall-v0.2.1) - 2024-12-29
47 |
48 | ### Fixed
49 |
50 | - *(deps)* update rust crate serde_json to v1.0.134 (#111)
51 |
52 | ## [0.2.0](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-tailcall-v0.1.4...gh-workflow-tailcall-v0.2.0) - 2024-12-11
53 |
54 | ### Other
55 |
56 | - unset release_always
57 |
58 | ## [0.1.4](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-tailcall-v0.1.3...gh-workflow-tailcall-v0.1.4) - 2024-12-05
59 |
60 | ### Other
61 |
62 | - updated the following local packages: gh-workflow
63 |
64 | ## [0.1.3](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-tailcall-v0.1.2...gh-workflow-tailcall-v0.1.3) - 2024-12-02
65 |
66 | ### Other
67 |
68 | - updated the following local packages: gh-workflow
69 |
70 | ## [0.1.2](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-tailcall-v0.1.1...gh-workflow-tailcall-v0.1.2) - 2024-11-29
71 |
72 | ### Other
73 |
74 | - updated the following local packages: gh-workflow
75 |
76 | ## [0.1.1](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-tailcall-v0.1.0...gh-workflow-tailcall-v0.1.1) - 2024-11-29
77 |
78 | ### Other
79 |
80 | - use gh-workflow-tailcall in the test
81 |
--------------------------------------------------------------------------------
/crates/gh-workflow-tailcall/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "gh-workflow-tailcall"
3 | version = "0.5.2"
4 | edition = "2021"
5 |
6 |
7 | description = "macros for gh-workflow"
8 | license = "Apache-2.0"
9 | documentation = "https://docs.rs/gh-workflow"
10 | homepage = "https://github.com/tailcallhq/gh-workflow"
11 | repository = "https://github.com/tailcallhq/gh-workflow"
12 | keywords = ["github", "actions", "workflow", "generator"]
13 |
14 | [dependencies]
15 | derive_setters = { version = "0.1.6" }
16 | gh-workflow = { path = "../gh-workflow", version = "0.6.0" }
17 | heck = "0.5.0"
18 |
19 | [dev-dependencies]
20 | insta = "1.40.0"
21 | pretty_assertions = "1.4.1"
22 |
--------------------------------------------------------------------------------
/crates/gh-workflow-tailcall/src/lib.rs:
--------------------------------------------------------------------------------
1 | mod standard;
2 |
3 | pub use gh_workflow::*;
4 | pub use standard::*;
5 |
--------------------------------------------------------------------------------
/crates/gh-workflow-tailcall/src/standard.rs:
--------------------------------------------------------------------------------
1 | //! StandardWorkflow is designed to be used for most Rust projects that are
2 | //! built at Tailcall. Though gh-workflow makes it much easier to write
3 | //! workflows you still need to constantly keep referring to the Github
4 | //! documentation to write your own workflows. This module saves all that time
5 | //! by using feature flags to enable or disable features that you want in your
6 | //! workflow. Based on the features enabled or disabled a workflow is generated.
7 |
8 | use ctx::Context;
9 | use derive_setters::Setters;
10 | use generate::Generate;
11 | use gh_workflow::error::Result;
12 | use gh_workflow::{Workflow as GHWorkflow, *};
13 | use heck::ToTitleCase;
14 | use release_plz::{Command, Release};
15 | use toolchain::Toolchain;
16 |
17 | /// Defines the test runner to use for running tests
18 | #[derive(Debug, Clone, Default)]
19 | pub enum TestRunner {
20 | /// Uses the default cargo test runner
21 | Cargo,
22 |
23 | /// Uses cargo-nextest for running tests
24 | #[default]
25 | Nextest,
26 | }
27 |
28 | #[derive(Debug, Clone, Setters)]
29 | pub struct StandardWorkflow {
30 | /// When enabled, a release job is added to the workflow.
31 | /// *IMPORTANT:* Ensure `secrets.CARGO_REGISTRY_TOKEN` is set for your
32 | /// github action.
33 | pub auto_release: bool,
34 |
35 | /// Name of the workflow.
36 | pub name: String,
37 |
38 | /// When enabled, a benchmark job is added to the workflow.
39 | pub benchmarks: bool,
40 |
41 | /// Auto-fixes the code after
42 | pub auto_fix: bool,
43 |
44 | /// Steps to be executed before the checkout step
45 | pub setup: Vec>,
46 |
47 | /// The test runner to use for running tests
48 | pub test_runner: TestRunner,
49 | }
50 |
51 | impl Default for StandardWorkflow {
52 | fn default() -> Self {
53 | Self {
54 | auto_release: false,
55 | name: "ci".into(),
56 | benchmarks: false,
57 | auto_fix: false,
58 | setup: Vec::new(),
59 | test_runner: TestRunner::default(),
60 | }
61 | }
62 | }
63 |
64 | impl StandardWorkflow {
65 | /// Initialize a job with common configuration including:
66 | /// - Permissions
67 | /// - Setup steps
68 | /// - Checkout step
69 | ///
70 | /// This reduces duplication across different job types.
71 | fn init_job(&self, name: impl ToString) -> Job {
72 | let mut job = Job::new(name).permissions(Permissions::default().contents(Level::Read));
73 |
74 | // Add setup steps in reverse order to maintain the correct sequence
75 | for step in self.setup.iter().rev() {
76 | job = job.add_step(step.clone());
77 | }
78 |
79 | job.add_step(Step::checkout())
80 | }
81 |
82 | /// Add a setup step to be executed before the checkout step.
83 | ///
84 | /// # Example
85 | /// ```ignore
86 | /// use gh_workflow_tailcall::*;
87 | /// let workflow = StandardWorkflow::default()
88 | /// .add_setup(Step::run("git config --global core.autocrlf false")
89 | /// .name("Configure git"));
90 | /// ```
91 | pub fn add_setup>>(mut self, step: S) -> Self {
92 | self.setup.push(step.into());
93 | self
94 | }
95 | }
96 |
97 | impl StandardWorkflow {
98 | /// Generates and tests the workflow file.
99 | pub fn generate(self) -> Result<()> {
100 | self.to_ci_workflow().generate()?;
101 | Generate::new(self.to_autofix_workflow())
102 | .name("autofix.yml")
103 | .generate()?;
104 | Ok(())
105 | }
106 |
107 | /// Converts the workflow into a Github workflow.
108 | fn to_autofix_workflow(&self) -> GHWorkflow {
109 | // NOTE: The workflow name needs to by `autofix.ci`
110 | GHWorkflow::new("autofix.ci")
111 | .add_env(self.workflow_flags())
112 | .on(self.workflow_event())
113 | .add_job("lint", self.lint_job(true))
114 | }
115 |
116 | /// Converts the workflow into a Github workflow.
117 | pub fn to_ci_workflow(&self) -> GHWorkflow {
118 | GHWorkflow::new(self.name.clone())
119 | .add_env(self.workflow_flags())
120 | .on(self.workflow_event())
121 | .add_job("build", self.test_job())
122 | .add_job("lint", self.lint_job(false))
123 | .add_job_when(
124 | self.auto_release,
125 | "release",
126 | self.release_job(Command::Release),
127 | )
128 | .add_job_when(
129 | self.auto_release,
130 | "release-pr",
131 | self.release_job(Command::ReleasePR),
132 | )
133 | }
134 |
135 | fn release_job(&self, cmd: Command) -> Job {
136 | self.init_job(cmd.to_string().to_title_case())
137 | .concurrency(
138 | Concurrency::new(Expression::new("release-${{github.ref}}"))
139 | .cancel_in_progress(false),
140 | )
141 | .cond(self.workflow_cond())
142 | .add_needs(self.test_job())
143 | .add_needs(self.lint_job(false))
144 | .add_env(Env::github())
145 | .add_env(Env::new(
146 | "CARGO_REGISTRY_TOKEN",
147 | "${{ secrets.CARGO_REGISTRY_TOKEN }}",
148 | ))
149 | .permissions(self.write_permissions())
150 | .add_step(Release::default().command(cmd))
151 | }
152 |
153 | fn lint_job(&self, auto_fix: bool) -> Job {
154 | let job = self.init_job(if auto_fix { "Lint Fix" } else { "Lint" });
155 |
156 | let job = if auto_fix {
157 | job.concurrency(
158 | Concurrency::new(Expression::new("autofix-${{github.ref}}"))
159 | .cancel_in_progress(false),
160 | )
161 | } else {
162 | job
163 | };
164 |
165 | job.add_step(
166 | Toolchain::default()
167 | .add_nightly()
168 | .add_clippy()
169 | .add_fmt()
170 | .cache(true)
171 | .cache_directories(vec![
172 | "~/.cargo/registry".into(),
173 | "~/.cargo/git".into(),
174 | "target".into(),
175 | ]),
176 | )
177 | .add_step(
178 | Cargo::new("fmt")
179 | .name("Cargo Fmt")
180 | .nightly()
181 | .add_args("--all")
182 | .add_args_when(!auto_fix, "--check"),
183 | )
184 | .add_step(
185 | Cargo::new("clippy")
186 | .name("Cargo Clippy")
187 | .nightly()
188 | .add_args_when(auto_fix, "--fix")
189 | .add_args_when(auto_fix, "--allow-dirty")
190 | .add_args("--all-features --workspace -- -D warnings"),
191 | )
192 | .add_step_when(
193 | auto_fix,
194 | Step::uses(
195 | "autofix-ci",
196 | "action",
197 | "551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef",
198 | ),
199 | )
200 | }
201 |
202 | /// Creates the "Build and Test" job for the workflow.
203 | fn test_job(&self) -> Job {
204 | self.init_job("Build and Test")
205 | .add_step(Toolchain::default().add_stable())
206 | .add_step_when(
207 | matches!(self.test_runner, TestRunner::Nextest),
208 | Cargo::new("install")
209 | .args("cargo-nextest --locked")
210 | .name("Install nextest"),
211 | )
212 | .add_step(match self.test_runner {
213 | TestRunner::Cargo => Cargo::new("test")
214 | .args("--all-features --workspace")
215 | .name("Cargo Test"),
216 | TestRunner::Nextest => Cargo::new("nextest")
217 | .args("run --all-features --workspace")
218 | .name("Cargo Nextest"),
219 | })
220 | .add_step_when(
221 | self.benchmarks,
222 | Cargo::new("bench").args("--workspace").name("Cargo Bench"),
223 | )
224 | }
225 |
226 | fn write_permissions(&self) -> Permissions {
227 | Permissions::default()
228 | .pull_requests(Level::Write)
229 | .packages(Level::Write)
230 | .contents(Level::Write)
231 | }
232 |
233 | fn workflow_cond(&self) -> Context {
234 | let is_main = Context::github().ref_().eq("refs/heads/main".into());
235 | let is_push = Context::github().event_name().eq("push".into());
236 |
237 | is_main.and(is_push)
238 | }
239 |
240 | fn workflow_event(&self) -> Event {
241 | Event::default()
242 | .push(Push::default().add_branch("main").add_tag("v*"))
243 | .pull_request(
244 | PullRequest::default()
245 | .add_type(PullRequestType::Opened)
246 | .add_type(PullRequestType::Synchronize)
247 | .add_type(PullRequestType::Reopened)
248 | .add_branch("main"),
249 | )
250 | }
251 |
252 | fn workflow_flags(&self) -> RustFlags {
253 | RustFlags::deny("warnings")
254 | }
255 | }
256 |
--------------------------------------------------------------------------------
/crates/gh-workflow-tailcall/tests/ci.rs:
--------------------------------------------------------------------------------
1 | use gh_workflow_tailcall::StandardWorkflow;
2 |
3 | #[test]
4 | fn generate() {
5 | StandardWorkflow::default()
6 | .auto_release(true)
7 | .auto_fix(true)
8 | .generate()
9 | .unwrap();
10 | }
11 |
--------------------------------------------------------------------------------
/crates/gh-workflow/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Unreleased]
9 |
10 | ## [0.6.0](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-v0.5.10...gh-workflow-v0.6.0) - 2025-05-06
11 |
12 | ### Added
13 |
14 | - *(event)* add tags filter to Push struct for event handling ([#157](https://github.com/tailcallhq/gh-workflow/pull/157))
15 |
16 | ## [0.5.10](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-v0.5.9...gh-workflow-v0.5.10) - 2025-01-29
17 |
18 | ### Added
19 |
20 | - add get method to Jobs struct for retrieving jobs by key (#134)
21 |
22 | ## [0.5.9](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-v0.5.8...gh-workflow-v0.5.9) - 2025-01-19
23 |
24 | ### Fixed
25 |
26 | - correct cargo install command in CI workflow and standard workflow
27 |
28 | ## [0.5.8](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-v0.5.7...gh-workflow-v0.5.8) - 2025-01-13
29 |
30 | ### Added
31 |
32 | - add caching support for Cargo toolchain in CI workflows
33 |
34 | ## [0.5.7](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-v0.5.6...gh-workflow-v0.5.7) - 2024-12-29
35 |
36 | ### Fixed
37 |
38 | - *(deps)* update rust crate serde_json to v1.0.134 (#111)
39 |
40 | ## [0.5.6](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-v0.5.5...gh-workflow-v0.5.6) - 2024-12-11
41 |
42 | ### Other
43 |
44 | - unset release_always
45 |
46 | ## [0.5.5](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-v0.5.4...gh-workflow-v0.5.5) - 2024-12-05
47 |
48 | ### Other
49 |
50 | - add readme
51 |
52 | ## [0.5.4](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-v0.5.3...gh-workflow-v0.5.4) - 2024-12-02
53 |
54 | ### Fixed
55 |
56 | - jobs dependency id generator ([#94](https://github.com/tailcallhq/gh-workflow/pull/94))
57 |
58 | ## [0.5.3](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-v0.5.2...gh-workflow-v0.5.3) - 2024-11-29
59 |
60 | ### Fixed
61 |
62 | - drop `v` prefix from `uses` API
63 |
64 | ## [0.5.2](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-v0.5.1...gh-workflow-v0.5.2) - 2024-11-29
65 |
66 | ### Other
67 |
68 | - use gh-workflow-tailcall in the test
69 |
70 | ## [0.5.1](https://github.com/tailcallhq/gh-workflow/compare/gh-workflow-v0.5.0...gh-workflow-v0.5.1) - 2024-11-29
71 |
72 | ### Other
73 |
74 | - *(gh-workflow-macros)* release v0.5.0 ([#86](https://github.com/tailcallhq/gh-workflow/pull/86))
75 |
76 | ## [0.5.0](https://github.com/tailcallhq/gh-workflow/compare/v0.4.1...v0.5.0) - 2024-11-28
77 |
78 | ### Other
79 |
80 | - reset release flags
81 |
--------------------------------------------------------------------------------
/crates/gh-workflow/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "gh-workflow"
3 | version = "0.6.0"
4 | edition = "2021"
5 |
6 | description = "A type-safe GitHub Actions workflow generator"
7 | license = "Apache-2.0"
8 | documentation = "https://docs.rs/gh-workflow"
9 | homepage = "https://github.com/tailcallhq/gh-workflow"
10 | repository = "https://github.com/tailcallhq/gh-workflow"
11 | keywords = ["github", "actions", "workflow", "generator"]
12 | readme = "../../README.md"
13 |
14 | [dependencies]
15 | async-trait = "0.1.83"
16 | derive_more = { version = "2.0.0", features = ["from", "deref", "deref_mut"] }
17 | derive_setters = "0.1.6"
18 | indexmap = { version = "2.6.0", features = ["serde"] }
19 | merge = "0.1.0"
20 | serde = { version = "1.0.210", features = ["derive"] }
21 | serde_json = { version = "1.0.128" }
22 | serde_yaml = "0.9.34"
23 | strum_macros = "0.27.0"
24 | gh-workflow-macros = { path = "../gh-workflow-macros", version = "0.6.0" }
25 |
26 | [dev-dependencies]
27 | insta = "1.40.0"
28 | pretty_assertions = "1.4.1"
29 |
--------------------------------------------------------------------------------
/crates/gh-workflow/src/cargo.rs:
--------------------------------------------------------------------------------
1 | use derive_setters::Setters;
2 |
3 | use crate::toolchain::Version;
4 | use crate::{Run, Step};
5 |
6 | #[derive(Clone, Setters)]
7 | #[setters(strip_option, into)]
8 | pub struct Cargo {
9 | /// The command to be executed for eg: fmt, clippy, build, test, etc.
10 | pub command: String,
11 |
12 | /// The unique identifier of the Step.
13 | pub id: Option,
14 |
15 | /// Name of the Step
16 | pub name: Option,
17 |
18 | /// Toolchain to be used for example `+nightly`.
19 | pub toolchain: Option,
20 |
21 | /// Arguments to be passed to the cargo command.
22 | #[setters(skip)]
23 | pub args: Vec,
24 | }
25 |
26 | impl Cargo {
27 | /// Creates a new `Cargo` instance with the specified command.
28 | pub fn new(cmd: T) -> Cargo {
29 | Cargo {
30 | command: cmd.to_string(),
31 | id: Default::default(),
32 | name: Default::default(),
33 | toolchain: Default::default(),
34 | args: Default::default(),
35 | }
36 | }
37 |
38 | /// Sets the toolchain to nightly.
39 | pub fn nightly(mut self) -> Self {
40 | self.toolchain = Some(Version::Nightly);
41 | self
42 | }
43 |
44 | /// Sets the arguments for the cargo command. If arguments are already set,
45 | /// it will be overwritten.
46 | pub fn args(mut self, args: T) -> Self {
47 | self.args = vec![args.to_string()];
48 | self
49 | }
50 |
51 | /// Adds additional arguments to the cargo command.
52 | pub fn add_args(mut self, args: T) -> Self {
53 | self.args.extend(
54 | args.to_string()
55 | .split_whitespace()
56 | .map(|s| s.to_string())
57 | .collect::>(),
58 | );
59 | self
60 | }
61 |
62 | /// Adds the arguments to the cargo command when a condition is met.
63 | pub fn add_args_when(self, when: bool, args: T) -> Self {
64 | if when {
65 | self.add_args(args)
66 | } else {
67 | self
68 | }
69 | }
70 | }
71 |
72 | impl From for Step {
73 | fn from(value: Cargo) -> Self {
74 | let mut command = vec!["cargo".to_string()];
75 |
76 | if let Some(toolchain) = value.toolchain {
77 | command.push(format!("+{toolchain}"));
78 | }
79 |
80 | command.push(value.command);
81 |
82 | // Extend the command with non-empty arguments
83 | command.extend(
84 | value
85 | .args
86 | .into_iter()
87 | .map(|arg| arg.trim().to_string())
88 | .filter(|arg| !arg.is_empty()),
89 | );
90 |
91 | let mut step = Step::run(command.join(" "));
92 |
93 | if let Some(id) = value.id {
94 | step = step.id(id);
95 | }
96 |
97 | if let Some(name) = value.name {
98 | step = step.name(name);
99 | }
100 |
101 | step
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/crates/gh-workflow/src/comment.yml:
--------------------------------------------------------------------------------
1 | # -------------------------------------------------------------------
2 | # ------------------------------- WARNING ---------------------------
3 | # -------------------------------------------------------------------
4 | #
5 | # This file was automatically generated by gh-workflows using the
6 | # gh-workflow-gen bin. You should add and commit this file to your
7 | # git repository. **DO NOT EDIT THIS FILE BY HAND!** Any manual changes
8 | # will be lost if the file is regenerated.
9 | #
10 | # To make modifications, update your `build.rs` configuration to adjust
11 | # the workflow description as needed, then regenerate this file to apply
12 | # those changes.
13 | #
14 | # -------------------------------------------------------------------
15 | # ----------------------------- END WARNING -------------------------
16 | # -------------------------------------------------------------------
17 |
--------------------------------------------------------------------------------
/crates/gh-workflow/src/ctx.rs:
--------------------------------------------------------------------------------
1 | //! A type-safe implementation of workflow context:
2 |
3 | use std::fmt;
4 | use std::marker::PhantomData;
5 | use std::rc::Rc;
6 |
7 | use gh_workflow_macros::Context;
8 |
9 | use crate::Expression;
10 |
11 | #[derive(Clone)]
12 | pub struct Context {
13 | marker: PhantomData,
14 | step: Step,
15 | }
16 |
17 | #[derive(Default, Clone)]
18 | enum Step {
19 | #[default]
20 | Root,
21 | Select {
22 | name: Rc,
23 | object: Box,
24 | },
25 | Eq {
26 | left: Box,
27 | right: Box,
28 | },
29 | And {
30 | left: Box,
31 | right: Box,
32 | },
33 | Or {
34 | left: Box,
35 | right: Box,
36 | },
37 | Literal(String),
38 | Concat {
39 | left: Box,
40 | right: Box,
41 | },
42 | }
43 |
44 | impl Context {
45 | fn new() -> Self {
46 | Context { marker: PhantomData, step: Step::Root }
47 | }
48 |
49 | fn select(&self, path: impl Into) -> Context {
50 | Context {
51 | marker: PhantomData,
52 | step: Step::Select {
53 | name: Rc::new(path.into()),
54 | object: Box::new(self.step.clone()),
55 | },
56 | }
57 | }
58 |
59 | pub fn eq(&self, other: Context) -> Context {
60 | Context {
61 | marker: Default::default(),
62 | step: Step::Eq {
63 | left: Box::new(self.step.clone()),
64 | right: Box::new(other.step.clone()),
65 | },
66 | }
67 | }
68 |
69 | pub fn and(&self, other: Context) -> Context {
70 | Context {
71 | marker: Default::default(),
72 | step: Step::And {
73 | left: Box::new(self.step.clone()),
74 | right: Box::new(other.step.clone()),
75 | },
76 | }
77 | }
78 |
79 | pub fn or(&self, other: Context) -> Context {
80 | Context {
81 | marker: Default::default(),
82 | step: Step::Or {
83 | left: Box::new(self.step.clone()),
84 | right: Box::new(other.step.clone()),
85 | },
86 | }
87 | }
88 | }
89 |
90 | impl Context {
91 | pub fn concat(&self, other: Context) -> Context {
92 | Context {
93 | marker: Default::default(),
94 | step: Step::Concat {
95 | left: Box::new(self.step.clone()),
96 | right: Box::new(other.step),
97 | },
98 | }
99 | }
100 | }
101 |
102 | #[allow(unused)]
103 | #[derive(Context)]
104 | pub struct Github {
105 | /// The name of the action currently running, or the id of a step.
106 | action: String,
107 | /// The path where an action is located. This property is only supported in
108 | /// composite actions.
109 | action_path: String,
110 | /// For a step executing an action, this is the ref of the action being
111 | /// executed.
112 | action_ref: String,
113 | /// For a step executing an action, this is the owner and repository name of
114 | /// the action.
115 | action_repository: String,
116 | /// For a composite action, the current result of the composite action.
117 | action_status: String,
118 | /// The username of the user that triggered the initial workflow run.
119 | actor: String,
120 | /// The account ID of the person or app that triggered the initial workflow
121 | /// run.
122 | actor_id: String,
123 | /// The URL of the GitHub REST API.
124 | api_url: String,
125 | /// The base_ref or target branch of the pull request in a workflow run.
126 | base_ref: String,
127 | /// Path on the runner to the file that sets environment variables from
128 | /// workflow commands.
129 | env: String,
130 | /// The full event webhook payload.
131 | event: serde_json::Value,
132 | /// The name of the event that triggered the workflow run.
133 | event_name: String,
134 | /// The path to the file on the runner that contains the full event webhook
135 | /// payload.
136 | event_path: String,
137 | /// The URL of the GitHub GraphQL API.
138 | graphql_url: String,
139 | /// The head_ref or source branch of the pull request in a workflow run.
140 | head_ref: String,
141 | /// The job id of the current job.
142 | job: String,
143 | /// The path of the repository.
144 | path: String,
145 | /// The short ref name of the branch or tag that triggered the workflow run.
146 | ref_name: String,
147 | /// true if branch protections are configured for the ref that triggered the
148 | /// workflow run.
149 | ref_protected: bool,
150 | /// The type of ref that triggered the workflow run. Valid values are branch
151 | /// or tag.
152 | ref_type: String,
153 | /// The owner and repository name.
154 | repository: String,
155 | /// The ID of the repository.
156 | repository_id: String,
157 | /// The repository owner's username.
158 | repository_owner: String,
159 | /// The repository owner's account ID.
160 | repository_owner_id: String,
161 | /// The Git URL to the repository.
162 | repository_url: String,
163 | /// The number of days that workflow run logs and artifacts are kept.
164 | retention_days: String,
165 | /// A unique number for each workflow run within a repository.
166 | run_id: String,
167 | /// A unique number for each run of a particular workflow in a repository.
168 | run_number: String,
169 | /// A unique number for each attempt of a particular workflow run in a
170 | /// repository.
171 | run_attempt: String,
172 | /// The source of a secret used in a workflow.
173 | secret_source: String,
174 | /// The URL of the GitHub server.
175 | server_url: String,
176 | /// The commit SHA that triggered the workflow.
177 | sha: String,
178 | /// A token to authenticate on behalf of the GitHub App installed on your
179 | /// repository.
180 | token: String,
181 | /// The username of the user that initiated the workflow run.
182 | triggering_actor: String,
183 | /// The name of the workflow.
184 | workflow: String,
185 | /// The ref path to the workflow.
186 | workflow_ref: String,
187 | /// The commit SHA for the workflow file.
188 | workflow_sha: String,
189 | /// The default working directory on the runner for steps.
190 | workspace: String,
191 | }
192 |
193 | impl Context {
194 | pub fn ref_(&self) -> Context {
195 | self.select("ref")
196 | }
197 | }
198 |
199 | impl fmt::Display for Step {
200 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 | match self {
202 | Step::Root => write!(f, ""),
203 | Step::Select { name, object } => {
204 | if matches!(**object, Step::Root) {
205 | write!(f, "{name}")
206 | } else {
207 | write!(f, "{object}.{name}")
208 | }
209 | }
210 | Step::Eq { left, right } => {
211 | write!(f, "{left} == {right}")
212 | }
213 | Step::And { left, right } => {
214 | write!(f, "{left} && {right}")
215 | }
216 | Step::Or { left, right } => {
217 | write!(f, "{left} || {right}")
218 | }
219 | Step::Literal(value) => {
220 | write!(f, "'{value}'")
221 | }
222 | Step::Concat { left, right } => {
223 | write!(f, "{left}{right}")
224 | }
225 | }
226 | }
227 | }
228 |
229 | impl fmt::Display for Context {
230 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
231 | write!(f, "${{{{ {} }}}}", self.step.to_string().replace('"', ""))
232 | }
233 | }
234 |
235 | impl From> for Expression {
236 | fn from(value: Context) -> Self {
237 | Expression::new(value.to_string())
238 | }
239 | }
240 |
241 | impl> From for Context {
242 | fn from(value: T) -> Self {
243 | Context {
244 | marker: Default::default(),
245 | step: Step::Literal(value.into()),
246 | }
247 | }
248 | }
249 |
250 | #[allow(unused)]
251 | #[derive(Context)]
252 | /// The job context contains information about the currently running job.
253 | pub struct Job {
254 | /// A unique number for each container in a job. This property is only
255 | /// available if the job uses a container.
256 | container: Container,
257 |
258 | /// The services configured for a job. This property is only available if
259 | /// the job uses service containers.
260 | services: Services,
261 |
262 | /// The status of the current job.
263 | status: JobStatus,
264 | }
265 |
266 | /// The status of a job execution
267 | #[derive(Clone)]
268 | pub enum JobStatus {
269 | /// The job completed successfully
270 | Success,
271 | /// The job failed
272 | Failure,
273 | /// The job was cancelled
274 | Cancelled,
275 | }
276 |
277 | #[derive(Context)]
278 | #[allow(unused)]
279 | /// Container information for a job. This is only available if the job runs in a
280 | /// container.
281 | pub struct Container {
282 | /// The ID of the container
283 | id: String,
284 | /// The container network
285 | network: String,
286 | }
287 |
288 | #[derive(Context)]
289 |
290 | /// Services configured for a job. This is only available if the job uses
291 | /// service containers.
292 | pub struct Services {}
293 |
294 | #[cfg(test)]
295 | mod test {
296 | use pretty_assertions::assert_eq;
297 |
298 | use super::*;
299 |
300 | #[test]
301 | fn test_expr() {
302 | let github = Context::github(); // Expr
303 |
304 | assert_eq!(github.to_string(), "${{ github }}");
305 |
306 | let action = github.action(); // Expr
307 | assert_eq!(action.to_string(), "${{ github.action }}");
308 |
309 | let action_path = github.action_path(); // Expr
310 | assert_eq!(action_path.to_string(), "${{ github.action_path }}");
311 | }
312 |
313 | #[test]
314 | fn test_expr_eq() {
315 | let github = Context::github();
316 | let action = github.action();
317 | let action_path = github.action_path();
318 |
319 | let expr = action.eq(action_path);
320 |
321 | assert_eq!(
322 | expr.to_string(),
323 | "${{ github.action == github.action_path }}"
324 | );
325 | }
326 |
327 | #[test]
328 | fn test_expr_and() {
329 | let push = Context::github().event_name().eq("push".into());
330 | let main = Context::github().ref_().eq("ref/heads/main".into());
331 | let expr = push.and(main);
332 |
333 | assert_eq!(
334 | expr.to_string(),
335 | "${{ github.event_name == 'push' && github.ref == 'ref/heads/main' }}"
336 | )
337 | }
338 |
339 | #[test]
340 | fn test_expr_or() {
341 | let github = Context::github();
342 | let action = github.action();
343 | let action_path = github.action_path();
344 | let action_ref = github.action_ref();
345 |
346 | let expr = action.eq(action_path).or(action.eq(action_ref));
347 |
348 | assert_eq!(
349 | expr.to_string(),
350 | "${{ github.action == github.action_path || github.action == github.action_ref }}"
351 | );
352 | }
353 | }
354 |
--------------------------------------------------------------------------------
/crates/gh-workflow/src/error.rs:
--------------------------------------------------------------------------------
1 | //! This module defines the `Error` enum and the `Result` type alias used
2 | //! throughout the crate.
3 |
4 | #[derive(Debug, derive_more::From)]
5 | pub enum Error {
6 | IO(std::io::Error),
7 | Yaml(serde_yaml::Error),
8 | GitHubWorkflowMismatch,
9 | JobIdAlreadyExists(String),
10 | UTF8(std::string::FromUtf8Error),
11 | OutdatedWorkflow,
12 | MissingWorkflowFile(std::path::PathBuf),
13 | }
14 |
15 | pub type Result = std::result::Result;
16 |
--------------------------------------------------------------------------------
/crates/gh-workflow/src/event.rs:
--------------------------------------------------------------------------------
1 | #![allow(clippy::needless_update)]
2 |
3 | use std::collections::HashMap;
4 |
5 | use derive_setters::Setters;
6 | use merge::Merge;
7 | use serde::{Deserialize, Serialize};
8 |
9 | use crate::is_default;
10 |
11 | /// Represents all possible webhook events that can trigger a workflow
12 | /// See: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows
13 | #[derive(Default, Debug, Clone, Deserialize, Serialize, Merge, Setters, PartialEq, Eq)]
14 | #[setters(strip_option, into)]
15 | pub struct Event {
16 | #[serde(skip_serializing_if = "Option::is_none")]
17 | pub branch_protection_rule: Option,
18 | #[serde(skip_serializing_if = "Option::is_none")]
19 | pub check_run: Option,
20 | #[serde(skip_serializing_if = "Option::is_none")]
21 | pub check_suite: Option,
22 | #[serde(skip_serializing_if = "Option::is_none")]
23 | pub create: Option,
24 | #[serde(skip_serializing_if = "Option::is_none")]
25 | pub delete: Option,
26 | #[serde(skip_serializing_if = "Option::is_none")]
27 | pub deployment: Option,
28 | #[serde(skip_serializing_if = "Option::is_none")]
29 | pub deployment_status: Option,
30 | #[serde(skip_serializing_if = "Option::is_none")]
31 | pub discussion: Option,
32 | #[serde(skip_serializing_if = "Option::is_none")]
33 | pub discussion_comment: Option,
34 | #[serde(skip_serializing_if = "Option::is_none")]
35 | pub fork: Option,
36 | #[serde(skip_serializing_if = "Option::is_none")]
37 | pub gollum: Option,
38 | #[serde(skip_serializing_if = "Option::is_none")]
39 | pub issue_comment: Option,
40 | #[serde(skip_serializing_if = "Option::is_none")]
41 | pub issues: Option,
42 | #[serde(skip_serializing_if = "Option::is_none")]
43 | pub label: Option