├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── release-plz.yml │ └── rust.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENCE-APACHE ├── LICENCE-MIT ├── README.md ├── examples ├── create_a_gist.rs ├── create_org_secret.rs ├── create_repo_from_template.rs ├── create_repo_secret.rs ├── custom_client.rs ├── delete_repo.rs ├── device_flow.rs ├── get_code_scanning_alerts.rs ├── get_commit.rs ├── get_content.rs ├── get_dependabot_alerts.rs ├── get_rate_limit.rs ├── get_repo.rs ├── get_secret_scanning_alerts.rs ├── github_app_authentication.rs ├── github_app_authentication_manual.rs ├── github_schema.graphql ├── graphql_issues.rs ├── is_collab.rs ├── issues_query.graphql ├── list_all_workflow_runs.rs ├── list_forks.rs ├── list_gists_for_token_holder.rs ├── list_org_self_hosted_runners.rs ├── list_repos_for_authenticated_user.rs ├── list_repos_starred_by_authenticated_user.rs ├── merge_branch.rs ├── notifications.rs ├── paging_results.rs ├── poll_events.rs ├── poll_org_events.rs ├── poll_repo_events.rs ├── print_license.rs ├── print_pr_diff.rs ├── render_markdown.rs ├── search_issues.rs ├── star_unstar_a_gist.rs ├── unlock.rs └── update_pull_request_branch.rs ├── release-plz.toml ├── src ├── api.rs ├── api │ ├── actions.rs │ ├── actions │ │ └── self_hosted_runners.rs │ ├── activity.rs │ ├── activity │ │ └── notifications.rs │ ├── apps.rs │ ├── apps │ │ └── installations.rs │ ├── checks.rs │ ├── code_scannings.rs │ ├── code_scannings │ │ ├── list.rs │ │ └── update.rs │ ├── commits.rs │ ├── commits │ │ ├── associated_check_runs.rs │ │ ├── associated_pull_requests.rs │ │ ├── compare_commit.rs │ │ └── create_comment.rs │ ├── current.rs │ ├── events.rs │ ├── gists.rs │ ├── gists │ │ ├── list_commits.rs │ │ ├── list_forks.rs │ │ └── list_gists.rs │ ├── gitignore.rs │ ├── hooks.rs │ ├── hooks │ │ ├── list_deliveries.rs │ │ └── retry_delivery.rs │ ├── issues.rs │ ├── issues │ │ ├── create.rs │ │ ├── list.rs │ │ ├── list_labels.rs │ │ └── update.rs │ ├── licenses.rs │ ├── markdown.rs │ ├── orgs.rs │ ├── orgs │ │ ├── events.rs │ │ ├── list_members.rs │ │ ├── list_repos.rs │ │ └── secrets.rs │ ├── projects.rs │ ├── projects │ │ └── projects.rs │ ├── pulls.rs │ ├── pulls │ │ ├── comment.rs │ │ ├── create.rs │ │ ├── list.rs │ │ ├── merge.rs │ │ ├── specific_pr.rs │ │ ├── specific_pr │ │ │ ├── pr_comment.rs │ │ │ ├── pr_commit.rs │ │ │ ├── pr_reviews.rs │ │ │ └── pr_reviews │ │ │ │ ├── specific_review.rs │ │ │ │ └── specific_review │ │ │ │ └── list_comments.rs │ │ └── update.rs │ ├── ratelimit.rs │ ├── repos.rs │ ├── repos │ │ ├── branches.rs │ │ ├── collaborators.rs │ │ ├── commits.rs │ │ ├── contributors.rs │ │ ├── dependabot.rs │ │ ├── events.rs │ │ ├── file.rs │ │ ├── forks.rs │ │ ├── generate.rs │ │ ├── merges.rs │ │ ├── pulls.rs │ │ ├── release_assets.rs │ │ ├── releases.rs │ │ ├── secret_scanning_alerts.rs │ │ ├── secrets.rs │ │ ├── stargazers.rs │ │ ├── status.rs │ │ ├── tags.rs │ │ └── teams.rs │ ├── search.rs │ ├── teams.rs │ ├── teams │ │ ├── children.rs │ │ ├── create.rs │ │ ├── edit.rs │ │ ├── invitations.rs │ │ ├── list.rs │ │ ├── members.rs │ │ └── team_repos.rs │ ├── users.rs │ ├── users │ │ ├── follow.rs │ │ ├── user_blocks.rs │ │ ├── user_emails.rs │ │ ├── user_git_ssh_keys.rs │ │ ├── user_gpg_keys.rs │ │ ├── user_repos.rs │ │ ├── user_social_accounts.rs │ │ └── user_ssh_signing_keys.rs │ └── workflows.rs ├── auth.rs ├── body.rs ├── error.rs ├── etag.rs ├── from_response.rs ├── lib.rs ├── models.rs ├── models │ ├── actions.rs │ ├── activity.rs │ ├── apps.rs │ ├── checks.rs │ ├── code_scannings.rs │ ├── commits.rs │ ├── date_serde.rs │ ├── events.rs │ ├── events │ │ ├── payload.rs │ │ └── payload │ │ │ ├── commit_comment.rs │ │ │ ├── create.rs │ │ │ ├── delete.rs │ │ │ ├── fork.rs │ │ │ ├── gollum.rs │ │ │ ├── installation.rs │ │ │ ├── installation_repositories.rs │ │ │ ├── installation_target.rs │ │ │ ├── issue_comment.rs │ │ │ ├── issues.rs │ │ │ ├── member.rs │ │ │ ├── public.rs │ │ │ ├── pull_request.rs │ │ │ ├── pull_request_review.rs │ │ │ ├── pull_request_review_comment.rs │ │ │ ├── push.rs │ │ │ ├── release.rs │ │ │ ├── watch.rs │ │ │ └── workflow_run.rs │ ├── gists.rs │ ├── hooks.rs │ ├── issues.rs │ ├── orgs.rs │ ├── orgs │ │ └── secrets.rs │ ├── pulls.rs │ ├── reactions.rs │ ├── repos.rs │ ├── repos │ │ ├── dependabot.rs │ │ ├── secret_scanning_alert.rs │ │ └── secrets.rs │ ├── teams.rs │ ├── timelines.rs │ ├── webhook_events.rs │ ├── webhook_events │ │ ├── payload.rs │ │ └── payload │ │ │ ├── branch_protection_rule.rs │ │ │ ├── check_run.rs │ │ │ ├── check_suite.rs │ │ │ ├── code_scanning_alert.rs │ │ │ ├── commit_comment.rs │ │ │ ├── create.rs │ │ │ ├── delete.rs │ │ │ ├── dependabot_alert.rs │ │ │ ├── deploy_key.rs │ │ │ ├── deployment.rs │ │ │ ├── deployment_protection_rule.rs │ │ │ ├── deployment_status.rs │ │ │ ├── discussion.rs │ │ │ ├── discussion_comment.rs │ │ │ ├── fork.rs │ │ │ ├── github_app_authorization.rs │ │ │ ├── gollum.rs │ │ │ ├── installation.rs │ │ │ ├── installation_repositories.rs │ │ │ ├── installation_target.rs │ │ │ ├── issue_comment.rs │ │ │ ├── issues.rs │ │ │ ├── label.rs │ │ │ ├── marketplace_purchase.rs │ │ │ ├── member.rs │ │ │ ├── membership.rs │ │ │ ├── merge_group.rs │ │ │ ├── meta.rs │ │ │ ├── milestone.rs │ │ │ ├── org_block.rs │ │ │ ├── organization.rs │ │ │ ├── package.rs │ │ │ ├── page_build.rs │ │ │ ├── personal_access_token_request.rs │ │ │ ├── ping.rs │ │ │ ├── project.rs │ │ │ ├── project_card.rs │ │ │ ├── project_column.rs │ │ │ ├── projects_v2.rs │ │ │ ├── projects_v2_item.rs │ │ │ ├── public.rs │ │ │ ├── pull_request.rs │ │ │ ├── pull_request_review.rs │ │ │ ├── pull_request_review_comment.rs │ │ │ ├── pull_request_review_thread.rs │ │ │ ├── push.rs │ │ │ ├── registry_package.rs │ │ │ ├── release.rs │ │ │ ├── repository.rs │ │ │ ├── repository_advisory.rs │ │ │ ├── repository_dispatch.rs │ │ │ ├── repository_import.rs │ │ │ ├── repository_vulnerability_alert.rs │ │ │ ├── schedule.rs │ │ │ ├── secret_scanning_alert.rs │ │ │ ├── secret_scanning_alert_location.rs │ │ │ ├── security_advisory.rs │ │ │ ├── security_and_analysis.rs │ │ │ ├── sponsorship.rs │ │ │ ├── star.rs │ │ │ ├── status.rs │ │ │ ├── team.rs │ │ │ ├── team_add.rs │ │ │ ├── watch.rs │ │ │ ├── workflow_dispatch.rs │ │ │ ├── workflow_job.rs │ │ │ └── workflow_run.rs │ └── workflows.rs ├── page.rs ├── params.rs └── service │ ├── middleware │ ├── auth_header.rs │ ├── base_uri.rs │ ├── extra_headers.rs │ ├── mod.rs │ └── retry.rs │ └── mod.rs └── tests ├── actions_add_selected_repo_to_org_secret_test.rs ├── actions_delete_workflow_run_logs_test.rs ├── actions_remove_selected_repo_from_org_secret_test.rs ├── actions_self_hosted_runners.rs ├── actions_workflows_dispatches_test.rs ├── check_suites.rs ├── code_scanning_alert_update_test.rs ├── code_scanning_alerts_list_test.rs ├── code_scanning_analysis_test.rs ├── commit_associated_check_runs_tests.rs ├── current_user_orgs_test.rs ├── dependabot_alerts_test.rs ├── events_test.rs ├── follow_redirect.rs ├── generate_release_notes_test.rs ├── gists_test.rs ├── hooks_delivery_list.rs ├── issues_check_assignee_test.rs ├── issues_comments_delete_test.rs ├── issues_comments_reactions_delete_test.rs ├── issues_labels_delete_test.rs ├── issues_locking_test.rs ├── issues_reactions_delete_test.rs ├── issues_timeline_tests.rs ├── mock_error.rs ├── notifications_threads_test.rs ├── org_installations_test.rs ├── org_members_tests.rs ├── org_secrets_test.rs ├── projects_org_create_project_test.rs ├── projects_org_list_projects_test.rs ├── projects_project_delete_test.rs ├── projects_project_get_test.rs ├── projects_project_update_test.rs ├── projects_repo_create_project_test.rs ├── projects_repo_list_projects_test.rs ├── projects_user_create_project_test.rs ├── projects_user_list_projects_test.rs ├── pull_request_commits_test.rs ├── pull_request_review_comment_test.rs ├── pull_request_review_operations_test.rs ├── repo_contributors_test.rs ├── repo_delete_ref_test.rs ├── repo_secrets_test.rs ├── repos_commit_test.rs ├── repos_delete_test.rs ├── repos_events_test.rs ├── repos_is_collaborator_test.rs ├── repos_merges_test.rs ├── repos_releases_get_by_id.rs ├── repos_releases_get_by_tag.rs ├── repos_releases_get_latest.rs ├── repos_releases_list_test.rs ├── repos_stargazers_tests.rs ├── resources ├── check_dependabot_alerts.json ├── check_run_annotations.json ├── check_secrets_alerts.json ├── check_secrets_alerts_locations.json ├── check_suite.json ├── check_suite_preferences.json ├── codescanning_alert_error.json ├── codescanning_alert_single.json ├── codescanning_alerts_multiple.json ├── commit_check_runs.json ├── commit_comment_created_webhook_event.json ├── commit_comment_event.json ├── create_event.json ├── create_event_with_null_description.json ├── delete_event.json ├── fork_event.json ├── generate_release_notes.json ├── get_pull_request_review.json ├── get_pull_request_review_comments.json ├── gollum_event.json ├── hooks_delivery_list.json ├── installation_created_webhook_event.json ├── installation_deleted_webhook_event.json ├── installation_event.json ├── installation_new_permissions_accepted_webhook_event.json ├── installation_repositories_removed_webhook_event.json ├── issue_comment_created_webhook_event.json ├── issue_comment_deleted_webhook_event.json ├── issue_comment_edited_webhook_event.json ├── issue_comment_event.json ├── issues_event.json ├── issues_labeled_webhook_event.json ├── issues_list_timeline_events.json ├── issues_opened_webhook_event.json ├── issues_remove_label.json ├── list_check_suites_for_ref.json ├── member_event.json ├── org_members.json ├── org_public_key.json ├── org_secret.json ├── org_secrets.json ├── orgs_installation_event.json ├── ping_webhook_event.json ├── project.json ├── projects.json ├── public_event.json ├── pull_request_closed_webhook_event.json ├── pull_request_commits.json ├── pull_request_commits_empty_author_object.json ├── pull_request_event.json ├── pull_request_opened_webhook_event.json ├── pull_request_review_comment.json ├── pull_request_review_comment_event.json ├── pull_request_review_event.json ├── pull_request_synchronize_webhook_event.json ├── push_event.json ├── push_webhook_event.json ├── release_event.json ├── repo_contributors.json ├── repo_public_key.json ├── repo_secret.json ├── repo_secrets.json ├── repos_list_commits.json ├── repos_merges_201.json ├── repos_releases_get_by_id.json ├── repos_releases_get_by_tag.json ├── repos_releases_get_latest.json ├── repos_releases_list.json ├── repository_deleted_webhook_event.json ├── self_hosted_runner.json ├── self_hosted_runner_token.json ├── self_hosted_runners.json ├── stargazers.json ├── team_invitations.json ├── team_members.json ├── unknown_event.json ├── user_blocks.json ├── user_data.json ├── user_emails.json ├── user_git_ssh_key_created.json ├── user_git_ssh_keys.json ├── user_gpg_key_created.json ├── user_gpg_keys.json ├── user_membership_orgs_event.json ├── user_projects.json ├── user_repositories.json ├── user_social_accounts.json ├── user_ssh_signing_key_created.json ├── user_ssh_signing_keys.json ├── watch_event.json ├── workflow_run_event.json └── workflow_run_event_no_organization.json ├── secrets_alerts_test.rs ├── team_delete_test.rs ├── team_invitations_tests.rs ├── team_members_tests.rs ├── team_repos_tests.rs ├── user_blocks_tests.rs ├── user_deserialize_test.rs ├── user_emails_tests.rs ├── user_git_ssh_keys_tests.rs ├── user_gpg_keys_tests.rs ├── user_repositories_tests.rs ├── user_social_accounts_tests.rs └── user_ssh_signing_keys_tests.rs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: XAMPPRocky 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 99 9 | -------------------------------------------------------------------------------- /.github/workflows/release-plz.yml: -------------------------------------------------------------------------------- 1 | name: Release-plz 2 | 3 | permissions: 4 | pull-requests: write 5 | contents: write 6 | 7 | on: 8 | push: 9 | branches: 10 | - main 11 | 12 | jobs: 13 | 14 | release-plz: 15 | name: Release-plz 16 | runs-on: ubuntu-22.04 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v3 20 | with: 21 | fetch-depth: 0 22 | - name: Install Rust toolchain 23 | uses: dtolnay/rust-toolchain@stable 24 | - name: Run release-plz 25 | uses: MarcoIeni/release-plz-action@v0.5 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} 29 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | build: 9 | runs-on: ${{ matrix.os }}-latest 10 | strategy: 11 | matrix: 12 | channel: [stable, beta, nightly] 13 | os: [ubuntu, macos, windows] 14 | features: 15 | - "" 16 | - "-F stream" 17 | steps: 18 | - uses: actions/checkout@v2 19 | - run: rustup default ${{ matrix.channel }} 20 | - run: cargo build --all-targets ${{ matrix.features }} 21 | - run: cargo test ${{ matrix.features }} 22 | 23 | wasm-build: 24 | runs-on: ubuntu-latest 25 | steps: 26 | - uses: actions/checkout@v2 27 | - run: rustup default stable 28 | - run: rustup target add wasm32-unknown-unknown 29 | - run: cargo build --target=wasm32-unknown-unknown --no-default-features 30 | 31 | clippy: 32 | runs-on: ubuntu-latest 33 | steps: 34 | - uses: actions/checkout@v2 35 | - run: cargo fmt --all -- --check 36 | - run: cargo clippy --tests --examples 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /Cargo.lock 2 | /target 3 | .idea 4 | -------------------------------------------------------------------------------- /LICENCE-APACHE: -------------------------------------------------------------------------------- 1 | Copyright 2016 Erin Power 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /LICENCE-MIT: -------------------------------------------------------------------------------- 1 | MIT License (MIT) 2 | 3 | Copyright (c) 2016 Erin Power 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/create_a_gist.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder().personal_token(token).build()?; 8 | 9 | println!("Creating a gist with hello world in rust on your account"); 10 | let gist = octocrab 11 | .gists() 12 | .create() 13 | .file( 14 | "hello_world.rs", 15 | "fn main() {\n println!(\"Hello World!\");\n}", 16 | ) 17 | // Optional Parameters 18 | .description("Hello World in Rust") 19 | .public(false) 20 | .send() 21 | .await?; 22 | println!("Done, created: {url}", url = gist.html_url); 23 | Ok(()) 24 | } 25 | -------------------------------------------------------------------------------- /examples/create_org_secret.rs: -------------------------------------------------------------------------------- 1 | use base64::{engine::general_purpose::STANDARD as B64, Engine}; 2 | use crypto_box::{self, aead::OsRng, PublicKey}; 3 | use octocrab::{ 4 | models::orgs::secrets::{CreateOrganizationSecret, Visibility}, 5 | Octocrab, 6 | }; 7 | use std::convert::TryInto; 8 | 9 | #[tokio::main] 10 | async fn main() -> octocrab::Result<()> { 11 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 12 | 13 | let octocrab = Octocrab::builder().personal_token(token).build()?; 14 | let org = octocrab.orgs("owner"); 15 | let secrets = org.secrets(); 16 | 17 | let public_key = secrets.get_public_key().await?; 18 | 19 | let crypto_pk = { 20 | let org_pk_bytes = B64.decode(public_key.key).unwrap(); 21 | let pk_array: [u8; crypto_box::KEY_SIZE] = org_pk_bytes.try_into().unwrap(); 22 | PublicKey::from(pk_array) 23 | }; 24 | 25 | let encrypted_value = crypto_box::seal(&mut OsRng, &crypto_pk, b"Very secret value").unwrap(); 26 | 27 | let result = secrets 28 | .create_or_update_secret( 29 | "TEST_SECRET_RS", 30 | &CreateOrganizationSecret { 31 | encrypted_value: &B64.encode(encrypted_value), 32 | key_id: &public_key.key_id, 33 | visibility: Visibility::Private, 34 | selected_repository_ids: None, 35 | }, 36 | ) 37 | .await?; 38 | 39 | println!("{:?}", result); 40 | 41 | Ok(()) 42 | } 43 | -------------------------------------------------------------------------------- /examples/create_repo_from_template.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder() 8 | .personal_token(token.to_string()) 9 | .build()?; 10 | 11 | let repository = octocrab.repos("rust-lang", "rust-template"); 12 | repository 13 | .generate("new-repository") 14 | .owner("new-owner") 15 | .description("New description") 16 | .private(true) 17 | .include_all_branches(true) 18 | .send() 19 | .await?; 20 | 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /examples/create_repo_secret.rs: -------------------------------------------------------------------------------- 1 | use base64::{engine::general_purpose::STANDARD as B64, Engine}; 2 | use crypto_box::{self, aead::OsRng, PublicKey}; 3 | use octocrab::{models::repos::secrets::CreateRepositorySecret, Octocrab}; 4 | use std::convert::TryInto; 5 | 6 | #[tokio::main] 7 | async fn main() -> octocrab::Result<()> { 8 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 9 | 10 | let octocrab = Octocrab::builder().personal_token(token).build()?; 11 | let repo = octocrab.repos("owner", "repo"); 12 | let secrets = repo.secrets(); 13 | 14 | let public_key = secrets.get_public_key().await?; 15 | 16 | let crypto_pk = { 17 | let pk_bytes = B64.decode(public_key.key).unwrap(); 18 | let pk_array: [u8; crypto_box::KEY_SIZE] = pk_bytes.try_into().unwrap(); 19 | PublicKey::from(pk_array) 20 | }; 21 | 22 | let encrypted_value = crypto_box::seal(&mut OsRng, &crypto_pk, b"Very secret value").unwrap(); 23 | 24 | let result = secrets 25 | .create_or_update_secret( 26 | "TEST_SECRET_RS", 27 | &CreateRepositorySecret { 28 | encrypted_value: &B64.encode(encrypted_value), 29 | key_id: &public_key.key_id, 30 | }, 31 | ) 32 | .await?; 33 | 34 | println!("{:?}", result); 35 | 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /examples/custom_client.rs: -------------------------------------------------------------------------------- 1 | use http::header::USER_AGENT; 2 | use http::Uri; 3 | use hyper_rustls::HttpsConnectorBuilder; 4 | 5 | use octocrab::service::middleware::base_uri::BaseUriLayer; 6 | use octocrab::service::middleware::extra_headers::ExtraHeadersLayer; 7 | use octocrab::{AuthState, OctocrabBuilder}; 8 | use std::sync::Arc; 9 | 10 | #[tokio::main] 11 | async fn main() -> octocrab::Result<()> { 12 | let connector = HttpsConnectorBuilder::new() 13 | .with_native_roots() // enabled the `rustls-native-certs` feature in hyper-rustls 14 | .unwrap() 15 | .https_only() 16 | .enable_http1() 17 | .build(); 18 | 19 | let client = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new()) 20 | .build(connector); 21 | let octocrab = OctocrabBuilder::new_empty() 22 | .with_service(client) 23 | .with_layer(&BaseUriLayer::new(Uri::from_static( 24 | "https://api.github.com", 25 | ))) 26 | .with_layer(&ExtraHeadersLayer::new(Arc::new(vec![( 27 | USER_AGENT, 28 | "octocrab".parse().unwrap(), 29 | )]))) 30 | .with_auth(AuthState::None) 31 | .build() 32 | .unwrap(); 33 | 34 | let repo = octocrab.repos("rust-lang", "rust").get().await?; 35 | 36 | let repo_metrics = octocrab 37 | .repos("rust-lang", "rust") 38 | .get_community_profile_metrics() 39 | .await?; 40 | 41 | println!( 42 | "{} has {} stars and {}% health percentage", 43 | repo.full_name.unwrap(), 44 | repo.stargazers_count.unwrap_or(0), 45 | repo_metrics.health_percentage 46 | ); 47 | 48 | Ok(()) 49 | } 50 | -------------------------------------------------------------------------------- /examples/delete_repo.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder().personal_token(token).build()?; 8 | octocrab.repos("rust-lang", "rust").delete().await?; 9 | 10 | Ok(()) 11 | } 12 | -------------------------------------------------------------------------------- /examples/device_flow.rs: -------------------------------------------------------------------------------- 1 | use http::header::ACCEPT; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let client_id = secrecy::SecretString::from(std::env::var("GITHUB_CLIENT_ID").unwrap()); 6 | let crab = octocrab::Octocrab::builder() 7 | .base_uri("https://github.com")? 8 | .add_header(ACCEPT, "application/json".to_string()) 9 | .build()?; 10 | 11 | let codes = crab 12 | .authenticate_as_device(&client_id, ["public_repo", "read:org"]) 13 | .await?; 14 | println!( 15 | "Go to {} and enter code {}", 16 | codes.verification_uri, codes.user_code 17 | ); 18 | let auth = codes.poll_until_available(&crab, &client_id).await?; 19 | 20 | println!("Authorization succeeded with access to {:?}", auth.scope); 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /examples/get_code_scanning_alerts.rs: -------------------------------------------------------------------------------- 1 | use http::header::ACCEPT; 2 | use octocrab::params::AlertState; 3 | use octocrab::Octocrab; 4 | 5 | const OWNER: &str = "org"; 6 | const REPO: &str = "some-repo"; 7 | 8 | #[tokio::main] 9 | async fn main() { 10 | // example for Code Scanning alerts API with OAuth GitHub App 11 | let client_id = secrecy::SecretString::from(std::env::var("GITHUB_CLIENT_ID").unwrap()); 12 | let crab = octocrab::Octocrab::builder() 13 | .base_uri("https://github.com") 14 | .unwrap() 15 | .add_header(ACCEPT, "application/json".to_string()) 16 | .build() 17 | .unwrap(); 18 | 19 | let codes = crab 20 | .authenticate_as_device(&client_id, ["security_events"]) 21 | .await 22 | .unwrap(); 23 | println!( 24 | "Go to {} and enter code {}", 25 | codes.verification_uri, codes.user_code 26 | ); 27 | let auth = codes.poll_until_available(&crab, &client_id).await.unwrap(); 28 | println!( 29 | "Auth: scope {:?}; token type {}", 30 | auth.scope, auth.token_type 31 | ); 32 | let octocrab = Octocrab::builder() 33 | .oauth(auth) 34 | .add_header(ACCEPT, "application/vnd.github+json".to_string()) 35 | .build() 36 | .unwrap(); 37 | // Get all Code Scanning alerts for a repo 38 | let a = octocrab 39 | .code_scannings(OWNER.to_owned(), REPO.to_owned()) 40 | .list() 41 | .send() 42 | .await 43 | .unwrap(); 44 | println!("{:?}", a); 45 | // Get a single Code Scanning alert 46 | let single_alert = octocrab 47 | .code_scannings(OWNER.to_owned(), REPO.to_owned()) 48 | .get(1) 49 | .await 50 | .unwrap(); 51 | println!("{:?}", single_alert); 52 | // Update (Open) a Code Scanning alert 53 | let updated_alert = octocrab 54 | .code_scannings(OWNER.to_owned(), REPO.to_owned()) 55 | .update(1) 56 | .state(AlertState::Open) 57 | .send() 58 | .await 59 | .unwrap(); 60 | println!("{:?}", updated_alert); 61 | } 62 | -------------------------------------------------------------------------------- /examples/get_commit.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder().personal_token(token).build()?; 8 | 9 | let commit = octocrab 10 | .commits("XAMPPRocky", "octocrab") 11 | .get("15c0e31") 12 | .await?; 13 | 14 | for file in commit.files.unwrap() { 15 | println!( 16 | "File: {file}, Additions: {additions}, Deletions: {deletions}", 17 | file = file.filename, 18 | additions = file.additions, 19 | deletions = file.deletions, 20 | ); 21 | } 22 | 23 | Ok(()) 24 | } 25 | -------------------------------------------------------------------------------- /examples/get_content.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder().personal_token(token).build()?; 8 | 9 | let content = octocrab 10 | .repos("rust-lang", "rust") 11 | .get_content() 12 | .send() 13 | .await?; 14 | 15 | println!("{} files/dirs in the repo root", content.items.len()); 16 | 17 | Ok(()) 18 | } 19 | -------------------------------------------------------------------------------- /examples/get_rate_limit.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> Result<(), Box> { 5 | let ratelimit = octocrab::instance().ratelimit().get().await?; 6 | println!("{}", serde_json::to_string_pretty(&ratelimit)?); 7 | 8 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 9 | let octocrab = Octocrab::builder().personal_token(token).build()?; 10 | let ratelimit = octocrab.ratelimit().get().await?; 11 | println!("{}", serde_json::to_string_pretty(&ratelimit)?); 12 | Ok(()) 13 | } 14 | -------------------------------------------------------------------------------- /examples/get_repo.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder().personal_token(token).build()?; 8 | 9 | let repo = octocrab.repos("rust-lang", "rust").get().await?; 10 | 11 | let repo_metrics = octocrab 12 | .repos("rust-lang", "rust") 13 | .get_community_profile_metrics() 14 | .await?; 15 | 16 | println!( 17 | "{} has {} stars and {}% health percentage", 18 | repo.full_name.unwrap(), 19 | repo.stargazers_count.unwrap_or(0), 20 | repo_metrics.health_percentage 21 | ); 22 | 23 | Ok(()) 24 | } 25 | -------------------------------------------------------------------------------- /examples/github_app_authentication.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let app_id = read_env_var("GITHUB_APP_ID").parse::().unwrap().into(); 6 | let app_private_key = read_env_var("GITHUB_APP_PRIVATE_KEY"); 7 | let key = jsonwebtoken::EncodingKey::from_rsa_pem(app_private_key.as_bytes()).unwrap(); 8 | 9 | let octocrab = Octocrab::builder().app(app_id, key).build()?; 10 | let _installations = octocrab.apps().installations().send().await.unwrap(); 11 | 12 | Ok(()) 13 | } 14 | 15 | fn read_env_var(var_name: &str) -> String { 16 | let err = format!("Missing environment variable: {var_name}"); 17 | std::env::var(var_name).expect(&err) 18 | } 19 | -------------------------------------------------------------------------------- /examples/github_app_authentication_manual.rs: -------------------------------------------------------------------------------- 1 | use octocrab::models::{InstallationRepositories, InstallationToken}; 2 | use octocrab::params::apps::CreateInstallationAccessToken; 3 | use octocrab::Octocrab; 4 | use url::Url; 5 | 6 | #[tokio::main] 7 | async fn main() -> octocrab::Result<()> { 8 | let app_id = read_env_var("GITHUB_APP_ID"); 9 | let app_private_key = read_env_var("GITHUB_APP_PRIVATE_KEY"); 10 | let key = jsonwebtoken::EncodingKey::from_rsa_pem(app_private_key.as_bytes()).unwrap(); 11 | 12 | let token = octocrab::auth::create_jwt(app_id.parse::().unwrap().into(), &key).unwrap(); 13 | 14 | let octocrab = Octocrab::builder().personal_token(token).build()?; 15 | 16 | let installations = octocrab 17 | .apps() 18 | .installations() 19 | .send() 20 | .await 21 | .unwrap() 22 | .take_items(); 23 | 24 | let mut create_access_token = CreateInstallationAccessToken::default(); 25 | create_access_token.repositories = vec!["octocrab".to_string()]; 26 | 27 | // By design, tokens are not forwarded to urls that contain an authority. This means we need to 28 | // extract the path from the url and use it to make the request. 29 | let access_token_url = 30 | Url::parse(installations[0].access_tokens_url.as_ref().unwrap()).unwrap(); 31 | 32 | let access: InstallationToken = octocrab 33 | .post(access_token_url.path(), Some(&create_access_token)) 34 | .await 35 | .unwrap(); 36 | 37 | let octocrab = octocrab::OctocrabBuilder::new() 38 | .personal_token(access.token) 39 | .build() 40 | .unwrap(); 41 | 42 | let installed_repos: InstallationRepositories = octocrab 43 | .get("/installation/repositories", None::<&()>) 44 | .await 45 | .unwrap(); 46 | let _repos = installed_repos.repositories; 47 | 48 | Ok(()) 49 | } 50 | 51 | fn read_env_var(var_name: &str) -> String { 52 | let err = format!("Missing environment variable: {var_name}"); 53 | std::env::var(var_name).expect(&err) 54 | } 55 | -------------------------------------------------------------------------------- /examples/is_collab.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder().personal_token(token).build()?; 8 | 9 | let repo = octocrab 10 | .repos("rust-lang", "rust") 11 | .is_collaborator("Roger-luo") 12 | .await?; 13 | 14 | if repo { 15 | println!("Roger-luo is a collaborator of rust-lang/rust"); 16 | } else { 17 | println!("Roger-luo is not a collaborator of rust-lang/rust"); 18 | } 19 | 20 | Ok(()) 21 | } 22 | -------------------------------------------------------------------------------- /examples/issues_query.graphql: -------------------------------------------------------------------------------- 1 | query IssuesQuery($owner: String!, $name: String!, $pageSize: Int!, $before: String) { 2 | repository(owner: $owner, name: $name) { 3 | issues(last: $pageSize, before: $before, states: OPEN) { 4 | nodes { 5 | title 6 | url 7 | } 8 | pageInfo { 9 | hasPreviousPage 10 | startCursor 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/list_all_workflow_runs.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let octocrab = Octocrab::builder().build()?; 6 | let runs = octocrab 7 | .workflows("rust-lang-ci", "rust") 8 | .list_all_runs() 9 | .per_page(2) 10 | .branch("master") 11 | .event("push") 12 | .status("success") 13 | .send() 14 | .await?; 15 | 16 | for run in runs { 17 | println!("Run:"); 18 | println!(" ID: {}", run.id); 19 | println!(" Name: {}", run.name); 20 | println!(" Event: {}", run.event); 21 | println!(" Branch: {}", run.head_branch); 22 | println!(" Created At: {}", run.created_at); 23 | println!(" Commit:"); 24 | println!(" Author: {}", run.head_commit.author.name); 25 | println!(" Message: {}", run.head_commit.message); 26 | println!() 27 | } 28 | 29 | Ok(()) 30 | } 31 | -------------------------------------------------------------------------------- /examples/list_forks.rs: -------------------------------------------------------------------------------- 1 | use octocrab::{params::repos::forks::Sort, Octocrab}; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder().personal_token(token).build()?; 8 | 9 | let forks = octocrab 10 | .repos("rust-lang", "rust") 11 | .list_forks() 12 | .sort(Sort::Oldest) 13 | .page(2u32) 14 | .per_page(35) 15 | .send() 16 | .await?; 17 | 18 | for f in forks { 19 | println!("fork: {}", f.owner.unwrap().login); 20 | } 21 | 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /examples/list_gists_for_token_holder.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder().personal_token(token).build()?; 8 | let current_user_name = octocrab.current().user().await?.login; 9 | let mut current_gist_page = octocrab 10 | .current() 11 | .list_gists_for_authenticated_user() 12 | .per_page(1) 13 | .send() 14 | .await?; 15 | 16 | let mut gists = current_gist_page.take_items(); 17 | while let Ok(Some(mut new_page)) = octocrab.get_page(¤t_gist_page.next).await { 18 | gists.extend(new_page.take_items()); 19 | current_gist_page = new_page; 20 | } 21 | 22 | println!( 23 | "User '{username}' has {count} gists:", 24 | username = current_user_name, 25 | count = gists.len() 26 | ); 27 | println!("id | url | [files...] | description"); 28 | for gist in gists { 29 | println!( 30 | "{id} | {url} | [{files}] | {description}", 31 | id = gist.id, 32 | url = gist.html_url, 33 | files = gist.files.into_keys().collect::>().join(", "), 34 | description = gist 35 | .description 36 | .unwrap_or("".into()) 37 | .escape_default(), 38 | ); 39 | } 40 | 41 | Ok(()) 42 | } 43 | -------------------------------------------------------------------------------- /examples/list_org_self_hosted_runners.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | // Note: this token must have the `admin:org` scope. An alternative use case 6 | // may be to authenticate as a GitHub App. See github_app_authentication.rs 7 | // for that. 8 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 9 | 10 | let octocrab = Octocrab::builder().personal_token(token).build()?; 11 | 12 | let runners = octocrab 13 | .actions() 14 | .list_org_self_hosted_runners("my-org") 15 | .per_page(100) 16 | .send() 17 | .await?; 18 | 19 | for runner in runners { 20 | println!("ID {}:", runner.id); 21 | println!(" Name:\t{}", runner.name); 22 | println!(" OS:\t\t{}", runner.os); 23 | println!(" Status:\t{}", runner.status); 24 | println!(" Busy:\t{}", runner.busy); 25 | print!(" Labels:\t["); 26 | for (index, label) in runner.labels.iter().enumerate() { 27 | print!("\"{}\"", label.name); 28 | if index != runner.labels.len() - 1 { 29 | print!(", "); 30 | } 31 | } 32 | println!("]"); 33 | } 34 | 35 | Ok(()) 36 | } 37 | -------------------------------------------------------------------------------- /examples/list_repos_for_authenticated_user.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder().personal_token(token).build()?; 8 | 9 | let my_repos = octocrab 10 | .current() 11 | .list_repos_for_authenticated_user() 12 | .type_("owner") 13 | .sort("updated") 14 | .per_page(100) 15 | .send() 16 | .await?; 17 | 18 | for repo in my_repos { 19 | println!("{}", repo.name); 20 | } 21 | 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /examples/list_repos_starred_by_authenticated_user.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder().personal_token(token).build()?; 8 | 9 | let repos = octocrab 10 | .current() 11 | .list_repos_starred_by_authenticated_user() 12 | .sort("updated") 13 | .per_page(100) 14 | .send() 15 | .await?; 16 | 17 | for repo in repos { 18 | println!("{}", repo.name); 19 | } 20 | 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /examples/merge_branch.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder().personal_token(token).build()?; 8 | octocrab 9 | .repos("XAMPPRocky", "octocrab") 10 | .merge("feature/1", "master") 11 | .commit_message("This is a custom merge-commit message") 12 | .send() 13 | .await?; 14 | 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /examples/notifications.rs: -------------------------------------------------------------------------------- 1 | use octocrab::Octocrab; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 6 | 7 | let octocrab = Octocrab::builder().personal_token(token).build()?; 8 | 9 | let notifications = octocrab 10 | .activity() 11 | .notifications() 12 | .list() 13 | .all(true) 14 | .send() 15 | .await?; 16 | for n in notifications { 17 | println!("unread notification: {}", n.subject.title); 18 | } 19 | 20 | Ok(()) 21 | } 22 | -------------------------------------------------------------------------------- /examples/paging_results.rs: -------------------------------------------------------------------------------- 1 | use octocrab::{params, Octocrab}; 2 | 3 | #[tokio::main] 4 | async fn main() -> octocrab::Result<()> { 5 | let octocrab = Octocrab::default(); 6 | 7 | let mut current_page = octocrab 8 | .orgs("rust-lang") 9 | .list_repos() 10 | .repo_type(params::repos::Type::Sources) 11 | .per_page(100) 12 | .send() 13 | .await?; 14 | let mut prs = current_page.take_items(); 15 | 16 | while let Ok(Some(mut new_page)) = octocrab.get_page(¤t_page.next).await { 17 | prs.extend(new_page.take_items()); 18 | 19 | for pr in prs.drain(..) { 20 | println!("{pr:?}"); 21 | } 22 | 23 | current_page = new_page; 24 | } 25 | 26 | Ok(()) 27 | } 28 | -------------------------------------------------------------------------------- /examples/poll_events.rs: -------------------------------------------------------------------------------- 1 | use octocrab::{etag::Etagged, models::events::Event, Page}; 2 | use std::collections::VecDeque; 3 | 4 | const DELAY_MS: u64 = 500; 5 | const TRACKING_CAPACITY: usize = 200; 6 | 7 | #[tokio::main] 8 | async fn main() -> octocrab::Result<()> { 9 | let mut etag = None; 10 | let mut seen = VecDeque::with_capacity(TRACKING_CAPACITY); 11 | let octo = octocrab::instance(); 12 | loop { 13 | let response: Etagged> = octo.events().etag(etag).per_page(100).send().await?; 14 | if let Some(page) = response.value { 15 | for event in page { 16 | if !seen.contains(&event.id) { 17 | println!( 18 | "New event : id = {:?}, type = {:?}, time = {:?}", 19 | event.id, event.r#type, event.created_at, 20 | ); 21 | if seen.len() == TRACKING_CAPACITY { 22 | seen.pop_back(); 23 | } 24 | seen.push_front(event.id); 25 | } 26 | } 27 | } 28 | etag = response.etag; 29 | tokio::time::sleep(tokio::time::Duration::from_millis(DELAY_MS)).await; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/poll_org_events.rs: -------------------------------------------------------------------------------- 1 | use octocrab::{etag::Etagged, models::events::Event, Page}; 2 | use std::collections::VecDeque; 3 | 4 | const DELAY_MS: u64 = 500; 5 | const TRACKING_CAPACITY: usize = 20; 6 | 7 | #[tokio::main] 8 | async fn main() -> octocrab::Result<()> { 9 | let mut etag = None; 10 | let mut seen = VecDeque::with_capacity(TRACKING_CAPACITY); 11 | let octo = octocrab::instance(); 12 | loop { 13 | let response: Etagged> = octo 14 | .orgs("nixos") 15 | .events() 16 | .etag(etag) 17 | .per_page(10) 18 | .send() 19 | .await?; 20 | if let Some(page) = response.value { 21 | for event in page { 22 | // If an etag changes and we get a new page, this page may contain events we have 23 | // already seen along with new events. So, keep track of the ones we have seen for 24 | // each page, this will be at most 20 events - the current page of 10 events and 25 | // the last page. 26 | if !seen.contains(&event.id) { 27 | println!( 28 | "New event : id = {:?}, repo = {:?}, type = {:?}, time = {:?}", 29 | event.id, event.repo.name, event.r#type, event.created_at 30 | ); 31 | if seen.len() == TRACKING_CAPACITY { 32 | seen.pop_back(); 33 | } 34 | seen.push_front(event.id); 35 | } 36 | } 37 | } 38 | etag = response.etag; 39 | tokio::time::sleep(tokio::time::Duration::from_millis(DELAY_MS)).await; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/poll_repo_events.rs: -------------------------------------------------------------------------------- 1 | use octocrab::{etag::Etagged, models::events::Event, Page}; 2 | use std::collections::VecDeque; 3 | 4 | const DELAY_MS: u64 = 500; 5 | const TRACKING_CAPACITY: usize = 20; 6 | 7 | #[tokio::main] 8 | async fn main() -> octocrab::Result<()> { 9 | let mut etag = None; 10 | let mut seen = VecDeque::with_capacity(TRACKING_CAPACITY); 11 | let octo = octocrab::instance(); 12 | loop { 13 | let response: Etagged> = octo 14 | .repos("nixos", "nixpkgs") 15 | .events() 16 | .etag(etag) 17 | .per_page(10) 18 | .send() 19 | .await?; 20 | if let Some(page) = response.value { 21 | for event in page { 22 | // If an etag changes and we get a new page, this page may contain events we have 23 | // already seen along with new events. So, keep track of the ones we have seen for 24 | // each page, this will be at most 20 events - the current page of 10 events and 25 | // the last page. 26 | if !seen.contains(&event.id) { 27 | println!( 28 | "New event : id = {:?}, type = {:?}, time = {:?}", 29 | event.id, event.r#type, event.created_at 30 | ); 31 | if seen.len() == TRACKING_CAPACITY { 32 | seen.pop_back(); 33 | } 34 | seen.push_front(event.id); 35 | } 36 | } 37 | } 38 | etag = response.etag; 39 | tokio::time::sleep(tokio::time::Duration::from_millis(DELAY_MS)).await; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/print_license.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() -> octocrab::Result<()> { 3 | let license = octocrab::instance() 4 | .repos("rust-lang", "rust") 5 | .license() 6 | .await?; 7 | 8 | println!("{license:#?}"); 9 | 10 | Ok(()) 11 | } 12 | -------------------------------------------------------------------------------- /examples/print_pr_diff.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() -> octocrab::Result<()> { 3 | let diff = octocrab::instance() 4 | .pulls("rust-lang", "rust") 5 | .get_diff(72033) 6 | .await?; 7 | 8 | println!("{diff}"); 9 | 10 | Ok(()) 11 | } 12 | -------------------------------------------------------------------------------- /examples/render_markdown.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() -> octocrab::Result<()> { 3 | let markdown = "**Markdown**"; 4 | print!( 5 | "{}", 6 | octocrab::instance().markdown().render_raw(markdown).await? 7 | ); 8 | Ok(()) 9 | } 10 | -------------------------------------------------------------------------------- /examples/search_issues.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() -> Result<(), Box> { 3 | let octocrab = octocrab::Octocrab::builder() 4 | .personal_token(std::env::var("GITHUB_TOKEN").unwrap()) 5 | .build()?; 6 | 7 | match octocrab 8 | .search() 9 | .issues_and_pull_requests("tokei is:pr") 10 | .send() 11 | .await 12 | { 13 | Ok(page) => println!("{page:#?}"), 14 | Err(error) => println!("{error:#?}"), 15 | } 16 | 17 | Ok(()) 18 | } 19 | -------------------------------------------------------------------------------- /examples/unlock.rs: -------------------------------------------------------------------------------- 1 | #[tokio::main] 2 | async fn main() -> octocrab::Result<()> { 3 | let api = octocrab::instance(); 4 | let issues_api = api.issues("rust-lang", "rust"); 5 | let one_issue = issues_api.list().per_page(1).send().await?.take_items(); 6 | issues_api.unlock(one_issue.first().unwrap().number).await?; 7 | 8 | Ok(()) 9 | } 10 | -------------------------------------------------------------------------------- /examples/update_pull_request_branch.rs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rust-script 2 | 3 | //! Dependencies can be specified in the script file itself as follows: 4 | //! 5 | //! ```cargo 6 | //! [dependencies] 7 | //! tokio = { version = "1.6.1", default-features = false, features = ["macros", "rt-multi-thread", "time"] } 8 | //! octocrab = { path = "../" } 9 | //! ``` 10 | 11 | use octocrab::Octocrab; 12 | 13 | #[tokio::main] 14 | async fn main() -> octocrab::Result<()> { 15 | let token = std::env::var("GITHUB_TOKEN").expect("GITHUB_TOKEN env variable is required"); 16 | let octocrab = Octocrab::builder().personal_token(token).build()?; 17 | 18 | let update = octocrab 19 | .pulls("XAMPPRocky", "octocrab") 20 | .update_branch(200) 21 | .await?; 22 | 23 | println!("Result of pull request update: {update}",); 24 | 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /release-plz.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | pr_labels = ["release"] 3 | -------------------------------------------------------------------------------- /src/api.rs: -------------------------------------------------------------------------------- 1 | pub mod actions; 2 | pub mod activity; 3 | pub mod apps; 4 | pub mod checks; 5 | pub mod code_scannings; 6 | pub mod commits; 7 | pub mod current; 8 | pub mod events; 9 | pub mod gists; 10 | pub mod gitignore; 11 | pub mod hooks; 12 | pub mod issues; 13 | pub mod licenses; 14 | pub mod markdown; 15 | pub mod orgs; 16 | pub mod projects; 17 | pub mod pulls; 18 | pub mod ratelimit; 19 | pub mod repos; 20 | pub mod search; 21 | pub mod teams; 22 | pub mod users; 23 | pub mod workflows; 24 | -------------------------------------------------------------------------------- /src/api/activity.rs: -------------------------------------------------------------------------------- 1 | //! Github Activity API 2 | 3 | use crate::Octocrab; 4 | 5 | pub mod notifications; 6 | 7 | /// Handler for GitHub's activity API. 8 | /// 9 | /// Created with [`Octocrab::activity`]. 10 | pub struct ActivityHandler<'octo> { 11 | crab: &'octo Octocrab, 12 | } 13 | 14 | impl<'octo> ActivityHandler<'octo> { 15 | pub(crate) fn new(crab: &'octo Octocrab) -> Self { 16 | Self { crab } 17 | } 18 | 19 | /// Creates a `NotificationsHandler` for the current authenticated user. 20 | pub fn notifications(&self) -> notifications::NotificationsHandler<'octo> { 21 | notifications::NotificationsHandler::new(self.crab) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/api/code_scannings/update.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(serde::Serialize)] 4 | pub struct UpdateCodeScanningBuilder<'octo, 'a> { 5 | #[serde(skip)] 6 | handler: &'a CodeScanningHandler<'octo>, 7 | #[serde(skip)] 8 | number: u64, 9 | #[serde(skip_serializing_if = "Option::is_none")] 10 | state: Option, 11 | #[serde(skip_serializing_if = "Option::is_none")] 12 | dismissed_reason: Option, 13 | #[serde(skip_serializing_if = "Option::is_none")] 14 | dismissed_comment: Option, 15 | } 16 | 17 | impl<'octo, 'a> UpdateCodeScanningBuilder<'octo, 'a> { 18 | pub(crate) fn new(handler: &'a CodeScanningHandler<'octo>, number: u64) -> Self { 19 | Self { 20 | handler, 21 | number, 22 | state: None, 23 | dismissed_reason: None, 24 | dismissed_comment: None, 25 | } 26 | } 27 | 28 | /// The title of the code scanning. 29 | pub fn state(mut self, state: impl Into) -> Self { 30 | self.state = Some(state.into()); 31 | self 32 | } 33 | 34 | pub fn dismissed_reason(mut self, dismissed_reason: impl Into) -> Self { 35 | self.dismissed_reason = Some(dismissed_reason.into()); 36 | self 37 | } 38 | 39 | pub fn dismissed_comment(mut self, dismissed_comment: impl Into) -> Self { 40 | self.dismissed_comment = Some(dismissed_comment.into()); 41 | self 42 | } 43 | 44 | pub async fn send(self) -> Result { 45 | let route = format!( 46 | "/repos/{owner}/{repo}/code-scanning/alerts/{code_scanning}", 47 | owner = self.handler.owner, 48 | repo = self.handler.repo.as_ref().expect("Repository is required"), 49 | code_scanning = self.number, 50 | ); 51 | 52 | self.handler.crab.patch(route, Some(&self)).await 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/api/commits/associated_check_runs.rs: -------------------------------------------------------------------------------- 1 | use crate::commits::CommitHandler; 2 | use crate::models::checks::ListCheckRuns; 3 | use crate::params::repos::Reference; 4 | use crate::Result; 5 | 6 | #[derive(serde::Serialize)] 7 | pub struct AssociatedCheckRunsBuilder<'octo, 'r> { 8 | #[serde(skip)] 9 | handler: &'r CommitHandler<'octo>, 10 | #[serde(skip)] 11 | reference: Reference, 12 | #[serde(skip_serializing_if = "Option::is_none")] 13 | per_page: Option, 14 | #[serde(skip_serializing_if = "Option::is_none")] 15 | page: Option, 16 | } 17 | 18 | impl<'octo, 'r> AssociatedCheckRunsBuilder<'octo, 'r> { 19 | pub(crate) fn new(handler: &'r CommitHandler<'octo>, reference: impl Into) -> Self { 20 | Self { 21 | handler, 22 | reference: reference.into(), 23 | per_page: None, 24 | page: None, 25 | } 26 | } 27 | 28 | /// Results per page (max 100). 29 | pub fn per_page(mut self, per_page: impl Into) -> Self { 30 | self.per_page = Some(per_page.into()); 31 | self 32 | } 33 | 34 | /// Page number of the results to fetch. 35 | pub fn page(mut self, page: impl Into) -> Self { 36 | self.page = Some(page.into()); 37 | self 38 | } 39 | 40 | /// Send the actual request. 41 | pub async fn send(self) -> Result { 42 | let route = format!( 43 | "/repos/{owner}/{repo}/commits/{reference}/check-runs", 44 | owner = self.handler.owner, 45 | repo = self.handler.repo, 46 | reference = self.reference.full_ref_url() 47 | ); 48 | 49 | self.handler.crab.get(route, Some(&self)).await 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/api/gists/list_commits.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(serde::Serialize)] 4 | pub struct ListCommitsBuilder<'octo, 'b> { 5 | #[serde(skip)] 6 | handler: &'b GistsHandler<'octo>, 7 | #[serde(skip)] 8 | gist_id: String, 9 | #[serde(skip_serializing_if = "Option::is_none")] 10 | per_page: Option, 11 | #[serde(skip_serializing_if = "Option::is_none")] 12 | page: Option, 13 | } 14 | 15 | impl<'octo, 'b> ListCommitsBuilder<'octo, 'b> { 16 | pub(crate) fn new(handler: &'b GistsHandler<'octo>, gist_id: String) -> Self { 17 | Self { 18 | handler, 19 | gist_id, 20 | per_page: None, 21 | page: None, 22 | } 23 | } 24 | 25 | /// Results per page (max 100). 26 | pub fn per_page(mut self, per_page: impl Into) -> Self { 27 | self.per_page = Some(per_page.into()); 28 | self 29 | } 30 | 31 | /// Page number of the results to fetch. 32 | pub fn page(mut self, page: impl Into) -> Self { 33 | self.page = Some(page.into()); 34 | self 35 | } 36 | 37 | /// Sends the actual request. 38 | pub async fn send(self) -> crate::Result> { 39 | let route = format!("/gists/{gist_id}/commits", gist_id = self.gist_id); 40 | self.handler.crab.get(route, Some(&self)).await 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/api/gists/list_forks.rs: -------------------------------------------------------------------------------- 1 | use crate::{gists::GistsHandler, models::gists::Gist, Page, Result}; 2 | use serde; 3 | 4 | #[derive(serde::Serialize)] 5 | pub struct ListGistForksBuilder<'octo, 'b> { 6 | #[serde(skip)] 7 | handler: &'b GistsHandler<'octo>, 8 | #[serde(skip)] 9 | gist_id: String, 10 | #[serde(skip_serializing_if = "Option::is_none")] 11 | per_page: Option, 12 | #[serde(skip_serializing_if = "Option::is_none")] 13 | page: Option, 14 | } 15 | 16 | impl<'octo, 'b> ListGistForksBuilder<'octo, 'b> { 17 | pub(crate) fn new(handler: &'b GistsHandler<'octo>, gist_id: String) -> Self { 18 | Self { 19 | handler, 20 | gist_id, 21 | per_page: None, 22 | page: None, 23 | } 24 | } 25 | 26 | /// Set the `per_page` query parameter on the builder. 27 | /// 28 | /// Controls the number of results to return per "page" of results. 29 | /// The maximum value is 100 results per page retrieved. Values larger than 30 | /// `100` are clamped to `100` by GitHub's API 31 | pub fn per_page(mut self, count: u8) -> Self { 32 | self.per_page = Some(count); 33 | self 34 | } 35 | 36 | /// Sets the `page` query parameter on the builder. 37 | /// 38 | /// Controls which page of the result set should be retrieved. 39 | /// All pages are retrieved if this is omitted. 40 | pub fn page(mut self, page_num: u32) -> Self { 41 | self.page = Some(page_num); 42 | self 43 | } 44 | 45 | /// Sends the actual request to GitHub's API 46 | pub async fn send(self) -> Result> { 47 | let route = format!("/gists/{gist_id}/forks", gist_id = self.gist_id); 48 | self.handler.crab.get(route, Some(&self)).await 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/api/gitignore.rs: -------------------------------------------------------------------------------- 1 | //! The gitignore API 2 | 3 | use crate::error::HttpSnafu; 4 | use http::{request, Uri}; 5 | use snafu::ResultExt; 6 | 7 | use crate::Octocrab; 8 | 9 | /// Handler for GitHub's gitignore API. 10 | /// 11 | /// Created with [`Octocrab::gitignore`]. 12 | pub struct GitignoreHandler<'octo> { 13 | crab: &'octo Octocrab, 14 | } 15 | 16 | impl<'octo> GitignoreHandler<'octo> { 17 | pub(crate) fn new(crab: &'octo Octocrab) -> Self { 18 | Self { crab } 19 | } 20 | 21 | /// List all templates available to pass as an option when creating a 22 | /// repository. 23 | /// ```no_run 24 | /// # async fn run() -> octocrab::Result<()> { 25 | /// let list = octocrab::instance().gitignore().list().await?; 26 | /// # Ok(()) 27 | /// # } 28 | /// ``` 29 | pub async fn list(&self) -> crate::Result> { 30 | self.crab.get("/gitignore/templates", None::<&()>).await 31 | } 32 | 33 | /// Get the source of a single template. 34 | /// ```no_run 35 | /// # async fn run() -> octocrab::Result<()> { 36 | /// let gitignore = octocrab::instance().gitignore().get("C").await?; 37 | /// # Ok(()) 38 | /// # } 39 | /// ``` 40 | pub async fn get(&self, name: impl AsRef) -> crate::Result { 41 | let route = format!("/gitignore/templates/{name}", name = name.as_ref()); 42 | let uri = Uri::builder() 43 | .path_and_query(route) 44 | .build() 45 | .context(HttpSnafu)?; 46 | let mut request = request::Builder::new().method("GET").uri(uri); 47 | request = request.header(http::header::ACCEPT, crate::format_media_type("raw")); 48 | 49 | let request = self.crab.build_request(request, None::<&()>)?; 50 | 51 | let response = self.crab.execute(request).await?; 52 | self.crab.body_to_string(response).await 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/api/hooks.rs: -------------------------------------------------------------------------------- 1 | //! The hooks API. 2 | use crate::models::{HookDeliveryId, HookId}; 3 | use crate::Octocrab; 4 | 5 | mod list_deliveries; 6 | mod retry_delivery; 7 | 8 | pub use self::{list_deliveries::ListHooksDeliveriesBuilder, retry_delivery::RetryDeliveryBuilder}; 9 | 10 | /// A client to GitHub's webhooks API. 11 | /// 12 | /// Created with [`Octocrab::hooks`]. 13 | pub struct HooksHandler<'octo> { 14 | crab: &'octo Octocrab, 15 | owner: String, 16 | repo: Option, 17 | } 18 | 19 | impl<'octo> HooksHandler<'octo> { 20 | pub(crate) fn new(crab: &'octo Octocrab, owner: String) -> Self { 21 | Self { 22 | crab, 23 | owner, 24 | repo: None, 25 | } 26 | } 27 | 28 | pub fn repo(mut self, repo: String) -> Self { 29 | self.repo = Some(repo); 30 | self 31 | } 32 | 33 | /// Lists all of the `Delivery`s associated with the hook. 34 | /// ```no_run 35 | /// # async fn run() -> octocrab::Result<()> { 36 | /// let reviews = octocrab::instance() 37 | /// .hooks("owner") 38 | /// //.repo("repo") 39 | /// .list_deliveries(21u64.into()) 40 | /// .per_page(100) 41 | /// .page(2u32) 42 | /// .send() 43 | /// .await?; 44 | /// # Ok(()) 45 | /// # } 46 | /// ``` 47 | pub fn list_deliveries(&self, hook_id: HookId) -> ListHooksDeliveriesBuilder<'_, '_> { 48 | ListHooksDeliveriesBuilder::new(self, hook_id) 49 | } 50 | 51 | /// Retry a delivery. 52 | /// ```no_run 53 | /// # async fn run() -> octocrab::Result<()> { 54 | /// let reviews = octocrab::instance() 55 | /// .hooks("owner") 56 | /// //.repo("repo") 57 | /// .retry_delivery(20u64.into(), 21u64.into()) 58 | /// .send() 59 | /// .await?; 60 | /// # Ok(()) 61 | /// # } 62 | /// ``` 63 | pub fn retry_delivery( 64 | &self, 65 | hook_id: HookId, 66 | delivery_id: HookDeliveryId, 67 | ) -> RetryDeliveryBuilder<'_, '_> { 68 | RetryDeliveryBuilder::new(self, hook_id, delivery_id) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/api/hooks/list_deliveries.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | /// A builder pattern struct for listing hooks deliveries. 4 | /// 5 | /// created by [`HooksHandler::list_deliveries`] 6 | /// 7 | /// [`HooksHandler::list_deliveries`]: ./struct.HooksHandler.html#method.list_deliveries 8 | #[derive(serde::Serialize)] 9 | pub struct ListHooksDeliveriesBuilder<'octo, 'r> { 10 | #[serde(skip)] 11 | handler: &'r HooksHandler<'octo>, 12 | #[serde(skip)] 13 | hook_id: HookId, 14 | #[serde(skip_serializing_if = "Option::is_none")] 15 | per_page: Option, 16 | #[serde(skip_serializing_if = "Option::is_none")] 17 | page: Option, 18 | } 19 | impl<'octo, 'r> ListHooksDeliveriesBuilder<'octo, 'r> { 20 | pub(crate) fn new(handler: &'r HooksHandler<'octo>, hook_id: HookId) -> Self { 21 | Self { 22 | handler, 23 | hook_id, 24 | per_page: None, 25 | page: None, 26 | } 27 | } 28 | 29 | /// Results per page (max 100). 30 | pub fn per_page(mut self, per_page: impl Into) -> Self { 31 | self.per_page = Some(per_page.into()); 32 | self 33 | } 34 | 35 | /// Page number of the results to fetch. 36 | pub fn page(mut self, page: impl Into) -> Self { 37 | self.page = Some(page.into()); 38 | self 39 | } 40 | 41 | /// Send the actual request. 42 | pub async fn send(self) -> crate::Result> { 43 | let route = match self.handler.repo.clone() { 44 | Some(repo) => format!( 45 | "/repos/{}/{}/hooks/{}/deliveries", 46 | self.handler.owner, repo, self.hook_id 47 | ), 48 | None => format!( 49 | "/orgs/{}/hooks/{}/deliveries", 50 | self.handler.owner, self.hook_id 51 | ), 52 | }; 53 | self.handler.crab.get(route, Some(&self)).await 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/api/hooks/retry_delivery.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::error::HttpSnafu; 3 | use http::Uri; 4 | use snafu::ResultExt; 5 | 6 | /// A builder pattern struct for listing hooks deliveries. 7 | /// 8 | /// created by [`HooksHandler::retry_delivery`] 9 | /// 10 | /// [`HooksHandler::retry_delivery`]: ./struct.HooksHandler.html#method.retry_delivery 11 | #[derive(serde::Serialize)] 12 | pub struct RetryDeliveryBuilder<'octo, 'r> { 13 | #[serde(skip)] 14 | handler: &'r HooksHandler<'octo>, 15 | #[serde(skip)] 16 | hook_id: HookId, 17 | #[serde(skip)] 18 | delivery_id: HookDeliveryId, 19 | } 20 | impl<'octo, 'r> RetryDeliveryBuilder<'octo, 'r> { 21 | pub(crate) fn new( 22 | handler: &'r HooksHandler<'octo>, 23 | hook_id: HookId, 24 | delivery_id: HookDeliveryId, 25 | ) -> Self { 26 | Self { 27 | handler, 28 | hook_id, 29 | delivery_id, 30 | } 31 | } 32 | 33 | /// Send the actual request. 34 | pub async fn send(self) -> crate::Result<()> { 35 | let route = match self.handler.repo.clone() { 36 | Some(repo) => format!( 37 | "/repos/{}/{}/hooks/{}/deliveries/{}/attempts", 38 | self.handler.owner, repo, self.hook_id, self.delivery_id 39 | ), 40 | None => format!( 41 | "/orgs/{}/hooks/{}/deliveries/{}/attempts", 42 | self.handler.owner, self.hook_id, self.delivery_id 43 | ), 44 | }; 45 | 46 | let uri = Uri::builder() 47 | .path_and_query(route) 48 | .build() 49 | .context(HttpSnafu)?; 50 | crate::map_github_error(self.handler.crab._post(uri, None::<&()>).await?) 51 | .await 52 | .map(drop) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/api/licenses.rs: -------------------------------------------------------------------------------- 1 | //! Metadata about popular open source licenses and information about a 2 | //! project's license file. 3 | 4 | use crate::{models, Octocrab}; 5 | 6 | /// Handler for GitHub's license API. 7 | /// 8 | /// Created with [`Octocrab::licenses`]. 9 | pub struct LicenseHandler<'octo> { 10 | crab: &'octo Octocrab, 11 | } 12 | 13 | impl<'octo> LicenseHandler<'octo> { 14 | pub(crate) fn new(crab: &'octo Octocrab) -> Self { 15 | Self { crab } 16 | } 17 | 18 | /// List commonly used licenses. 19 | /// ```no_run 20 | /// # async fn run() -> octocrab::Result<()> { 21 | /// let licenses = octocrab::instance().licenses().list_commonly_used().await?; 22 | /// # Ok(()) 23 | /// # } 24 | /// ``` 25 | pub async fn list_commonly_used(&self) -> crate::Result> { 26 | self.crab.get("/licenses", None::<&()>).await 27 | } 28 | 29 | /// Get an individual license. 30 | /// ```no_run 31 | /// # async fn run() -> octocrab::Result<()> { 32 | /// let license = octocrab::instance().licenses().get("mit").await?; 33 | /// # Ok(()) 34 | /// # } 35 | /// ``` 36 | pub async fn get(&self, key: impl AsRef) -> crate::Result { 37 | self.crab 38 | .get(format!("/licenses/{}", key.as_ref()), None::<&()>) 39 | .await 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/api/orgs/list_members.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(serde::Serialize)] 4 | pub struct ListOrgMembersBuilder<'octo, 'r> { 5 | #[serde(skip)] 6 | handler: &'r OrgHandler<'octo>, 7 | #[serde(skip_serializing_if = "Option::is_none")] 8 | per_page: Option, 9 | #[serde(skip_serializing_if = "Option::is_none")] 10 | page: Option, 11 | } 12 | 13 | impl<'octo, 'r> ListOrgMembersBuilder<'octo, 'r> { 14 | pub fn new(handler: &'r OrgHandler<'octo>) -> Self { 15 | Self { 16 | handler, 17 | per_page: None, 18 | page: None, 19 | } 20 | } 21 | 22 | /// Results per page (max 100). 23 | pub fn per_page(mut self, per_page: impl Into) -> Self { 24 | self.per_page = Some(per_page.into()); 25 | self 26 | } 27 | 28 | /// Page number of the results to fetch. 29 | pub fn page(mut self, page: impl Into) -> Self { 30 | self.page = Some(page.into()); 31 | self 32 | } 33 | 34 | pub async fn send(self) -> crate::Result> { 35 | let route = format!("/orgs/{org}/members", org = self.handler.owner); 36 | self.handler.crab.get(route, Some(&self)).await 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/api/pulls/specific_pr/pr_comment.rs: -------------------------------------------------------------------------------- 1 | use serde_json::json; 2 | 3 | use crate::models::pulls::ReviewComment; 4 | use crate::models::CommentId; 5 | use crate::pulls::PullRequestHandler; 6 | 7 | #[derive(serde::Serialize)] 8 | pub struct SpecificPullRequestCommentBuilder<'octo, 'b> { 9 | #[serde(skip)] 10 | handler: &'b PullRequestHandler<'octo>, 11 | pr_number: u64, 12 | comment_id: CommentId, 13 | } 14 | 15 | impl<'octo, 'b> SpecificPullRequestCommentBuilder<'octo, 'b> { 16 | pub(crate) fn new( 17 | handler: &'b PullRequestHandler<'octo>, 18 | pr_number: u64, 19 | comment_id: CommentId, 20 | ) -> Self { 21 | Self { 22 | handler, 23 | comment_id, 24 | pr_number, 25 | } 26 | } 27 | 28 | pub async fn reply(&self, comment: impl Into) -> crate::Result { 29 | let route = format!( 30 | "/repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies", 31 | owner = self.handler.owner, 32 | repo = self.handler.repo, 33 | pull_number = self.pr_number, 34 | comment_id = self.comment_id 35 | ); 36 | self.handler 37 | .crab 38 | .post(route, Some(&json!({ "body": comment.into() }))) 39 | .await 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/api/pulls/specific_pr/pr_commit.rs: -------------------------------------------------------------------------------- 1 | use crate::pulls::PullRequestHandler; 2 | use serde::Serialize; 3 | 4 | use crate::models::repos::RepoCommit; 5 | 6 | #[derive(Serialize)] 7 | pub struct SpecificPullRequestCommitBuilder<'octo, 'r> { 8 | #[serde(skip)] 9 | handler: &'r PullRequestHandler<'octo>, 10 | #[serde(skip)] 11 | pr_number: u64, 12 | #[serde(skip_serializing_if = "Option::is_none")] 13 | per_page: Option, 14 | #[serde(skip_serializing_if = "Option::is_none")] 15 | page: Option, 16 | } 17 | 18 | impl<'octo, 'r> SpecificPullRequestCommitBuilder<'octo, 'r> { 19 | pub(crate) fn new(handler: &'r PullRequestHandler<'octo>, pr_number: u64) -> Self { 20 | Self { 21 | handler, 22 | pr_number, 23 | per_page: None, 24 | page: None, 25 | } 26 | } 27 | 28 | /// Results per page. 29 | pub fn per_page(mut self, per_page: impl Into) -> Self { 30 | self.per_page = Some(per_page.into()); 31 | self 32 | } 33 | 34 | /// Page number of the results to fetch. 35 | pub fn page(mut self, page: impl Into) -> Self { 36 | self.page = Some(page.into()); 37 | self 38 | } 39 | 40 | /// Send the actual request. 41 | pub async fn send(self) -> crate::Result> { 42 | let route = format!( 43 | "/repos/{owner}/{repo}/pulls/{pr}/commits", 44 | owner = self.handler.owner, 45 | repo = self.handler.repo, 46 | pr = self.pr_number, 47 | ); 48 | 49 | self.handler.crab.get(route, Some(&self)).await 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/api/pulls/specific_pr/pr_reviews.rs: -------------------------------------------------------------------------------- 1 | use crate::pulls::specific_pr::pr_reviews::specific_review::SpecificReviewBuilder; 2 | use crate::pulls::PullRequestHandler; 3 | 4 | pub mod specific_review; 5 | 6 | #[derive(serde::Serialize)] 7 | pub struct ReviewsBuilder<'octo, 'b> { 8 | #[serde(skip)] 9 | handler: &'b PullRequestHandler<'octo>, 10 | #[serde(skip_serializing_if = "Option::is_none")] 11 | per_page: Option, 12 | #[serde(skip_serializing_if = "Option::is_none")] 13 | page: Option, 14 | pr_number: u64, 15 | } 16 | 17 | impl<'octo, 'b> ReviewsBuilder<'octo, 'b> { 18 | pub(crate) fn new(handler: &'b PullRequestHandler<'octo>, pr_number: u64) -> Self { 19 | Self { 20 | handler, 21 | per_page: None, 22 | page: None, 23 | pr_number, 24 | } 25 | } 26 | 27 | /// Creates a new `SpecificReviewBuilder` 28 | /// ```no_run 29 | /// # async fn run() -> octocrab::Result<()> { 30 | /// # let octocrab = octocrab::Octocrab::default(); 31 | /// use octocrab::params; 32 | /// 33 | /// let _ = octocrab.pulls("owner", "repo") 34 | /// .pull_number(42) 35 | /// .reviews() 36 | /// .review(42) 37 | /// .get() // + update, delete_pending, submit, dismiss, list_comments 38 | /// .await?; 39 | /// # Ok(()) 40 | /// # } 41 | /// ``` 42 | pub fn review(&self, review_id: u64) -> SpecificReviewBuilder<'octo, '_> { 43 | SpecificReviewBuilder::new(self.handler, self.pr_number, review_id) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/api/pulls/specific_pr/pr_reviews/specific_review/list_comments.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(serde::Serialize)] 4 | pub struct ListReviewCommentsBuilder<'octo, 'b> { 5 | #[serde(skip)] 6 | handler: &'b PullRequestHandler<'octo>, 7 | pr_number: u64, 8 | review_id: u64, 9 | #[serde(skip_serializing_if = "Option::is_none")] 10 | per_page: Option, 11 | #[serde(skip_serializing_if = "Option::is_none")] 12 | page: Option, 13 | } 14 | 15 | impl<'octo, 'b> ListReviewCommentsBuilder<'octo, 'b> { 16 | pub(crate) fn new( 17 | handler: &'b PullRequestHandler<'octo>, 18 | pr_number: u64, 19 | review_id: u64, 20 | ) -> Self { 21 | Self { 22 | handler, 23 | pr_number, 24 | review_id, 25 | per_page: None, 26 | page: None, 27 | } 28 | } 29 | 30 | /// Results per page (max 100). 31 | pub fn per_page(mut self, per_page: impl Into) -> Self { 32 | self.per_page = Some(per_page.into()); 33 | self 34 | } 35 | 36 | /// Page number of the results to fetch. 37 | pub fn page(mut self, page: impl Into) -> Self { 38 | self.page = Some(page.into()); 39 | self 40 | } 41 | 42 | /// Sends the actual request. 43 | pub async fn send(self) -> crate::Result> { 44 | let route = format!( 45 | "/repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments", 46 | owner = self.handler.owner, 47 | repo = self.handler.repo, 48 | pull_number = self.pr_number, 49 | review_id = self.review_id 50 | ); 51 | self.handler.crab.get(route, Some(&self)).await 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/api/ratelimit.rs: -------------------------------------------------------------------------------- 1 | //! Github RateLimit API 2 | 3 | use crate::{models, Octocrab, Result}; 4 | 5 | /// Handler for GitHub's rate_limit API. 6 | /// 7 | /// Created with [`Octocrab::ratelimit`]. 8 | pub struct RateLimitHandler<'octo> { 9 | crab: &'octo Octocrab, 10 | } 11 | 12 | impl<'octo> RateLimitHandler<'octo> { 13 | pub(crate) fn new(crab: &'octo Octocrab) -> Self { 14 | Self { crab } 15 | } 16 | 17 | /// Get the rate limit. 18 | /// ```no_run 19 | /// # async fn run() -> octocrab::Result<()> { 20 | /// let ratelimit = octocrab::instance() 21 | /// .ratelimit() 22 | /// .get() 23 | /// .await?; 24 | /// # Ok(()) 25 | /// # } 26 | /// ``` 27 | pub async fn get(&self) -> Result { 28 | self.crab.get("/rate_limit", None::<&()>).await 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/api/repos/branches.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(serde::Serialize)] 4 | pub struct ListBranchesBuilder<'octo, 'r> { 5 | #[serde(skip)] 6 | handler: &'r RepoHandler<'octo>, 7 | #[serde(skip_serializing_if = "Option::is_none")] 8 | protected: Option, 9 | #[serde(skip_serializing_if = "Option::is_none")] 10 | per_page: Option, 11 | #[serde(skip_serializing_if = "Option::is_none")] 12 | page: Option, 13 | } 14 | 15 | impl<'octo, 'r> ListBranchesBuilder<'octo, 'r> { 16 | pub fn new(handler: &'r RepoHandler<'octo>) -> Self { 17 | Self { 18 | handler, 19 | protected: None, 20 | per_page: None, 21 | page: None, 22 | } 23 | } 24 | 25 | /// Setting to true returns only protected branches. When set to false, only 26 | /// unprotected branches are returned. Omitting this parameter returns all 27 | /// branches. 28 | pub fn protected(mut self, protected: impl Into) -> Self { 29 | self.protected = Some(protected.into()); 30 | self 31 | } 32 | 33 | /// Results per page (max 100). 34 | pub fn per_page(mut self, per_page: impl Into) -> Self { 35 | self.per_page = Some(per_page.into()); 36 | self 37 | } 38 | 39 | /// Page number of the results to fetch. 40 | pub fn page(mut self, page: impl Into) -> Self { 41 | self.page = Some(page.into()); 42 | self 43 | } 44 | 45 | /// Sends the actual request. 46 | pub async fn send(self) -> Result> { 47 | let route = format!("/{}/branches", self.handler.repo); 48 | self.handler.crab.get(route, Some(&self)).await 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/api/repos/collaborators.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::params::teams::Permission; 3 | 4 | #[derive(serde::Serialize)] 5 | pub struct ListCollaboratorsBuilder<'octo, 'r> { 6 | #[serde(skip)] 7 | handler: &'r RepoHandler<'octo>, 8 | #[serde(skip_serializing_if = "Option::is_none")] 9 | per_page: Option, 10 | #[serde(skip_serializing_if = "Option::is_none")] 11 | page: Option, 12 | #[serde(skip_serializing_if = "Option::is_none")] 13 | permission: Option, 14 | } 15 | 16 | impl<'octo, 'r> ListCollaboratorsBuilder<'octo, 'r> { 17 | pub fn new(handler: &'r RepoHandler<'octo>) -> Self { 18 | Self { 19 | handler, 20 | per_page: None, 21 | page: None, 22 | permission: None, 23 | } 24 | } 25 | 26 | /// Results per page (max 100). 27 | pub fn per_page(mut self, per_page: impl Into) -> Self { 28 | self.per_page = Some(per_page.into()); 29 | self 30 | } 31 | 32 | /// Page number of the results to fetch. 33 | pub fn page(mut self, page: impl Into) -> Self { 34 | self.page = Some(page.into()); 35 | self 36 | } 37 | 38 | /// Filter collaborators by the permissions they have on the repository. 39 | /// If not specified, all collaborators will be returned. 40 | /// Can be one of: pull, triage, push, maintain, admin 41 | pub fn permission(mut self, permission: Permission) -> Self { 42 | self.permission = Some(permission); 43 | self 44 | } 45 | 46 | /// Sends the actual request. 47 | pub async fn send(self) -> crate::Result> { 48 | let route = format!("/{}/collaborators", self.handler.repo); 49 | self.handler.crab.get(route, Some(&self)).await 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/api/repos/contributors.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(serde::Serialize)] 4 | pub struct ListContributorsBuilder<'octo, 'r> { 5 | #[serde(skip)] 6 | handler: &'r RepoHandler<'octo>, 7 | #[serde(skip_serializing_if = "Option::is_none")] 8 | anon: Option, 9 | #[serde(skip_serializing_if = "Option::is_none")] 10 | per_page: Option, 11 | #[serde(skip_serializing_if = "Option::is_none")] 12 | page: Option, 13 | } 14 | 15 | impl<'octo, 'r> ListContributorsBuilder<'octo, 'r> { 16 | pub fn new(handler: &'r RepoHandler<'octo>) -> Self { 17 | Self { 18 | handler, 19 | anon: None, 20 | per_page: None, 21 | page: None, 22 | } 23 | } 24 | 25 | /// Set to 1 or true to include anonymous contributors in results. 26 | pub fn anon(mut self, include_anon: impl Into) -> Self { 27 | self.anon = Some(include_anon.into()); 28 | self 29 | } 30 | 31 | /// Results per page (max 100). 32 | pub fn per_page(mut self, per_page: impl Into) -> Self { 33 | self.per_page = Some(per_page.into()); 34 | self 35 | } 36 | 37 | /// Page number of the results to fetch. 38 | pub fn page(mut self, page: impl Into) -> Self { 39 | self.page = Some(page.into()); 40 | self 41 | } 42 | 43 | /// Sends the actual request. 44 | pub async fn send(self) -> crate::Result> { 45 | let route = format!("/{}/contributors", self.handler.repo); 46 | self.handler.crab.get(route, Some(&self)).await 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/api/repos/merges.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::from_response::FromResponse; 3 | 4 | #[derive(serde::Serialize)] 5 | pub struct MergeBranchBuilder<'octo, 'r> { 6 | #[serde(skip)] 7 | handler: &'r RepoHandler<'octo>, 8 | head: String, 9 | base: String, 10 | #[serde(skip_serializing_if = "Option::is_none")] 11 | commit_message: Option, 12 | } 13 | 14 | impl<'octo, 'r> MergeBranchBuilder<'octo, 'r> { 15 | pub fn new( 16 | handler: &'r RepoHandler<'octo>, 17 | head: impl Into, 18 | base: impl Into, 19 | ) -> Self { 20 | Self { 21 | handler, 22 | head: head.into(), 23 | base: base.into(), 24 | commit_message: None, 25 | } 26 | } 27 | 28 | /// The message to use for the merge commit. 29 | pub fn commit_message(mut self, commit_message: impl Into) -> Self { 30 | self.commit_message = Some(commit_message.into()); 31 | self 32 | } 33 | 34 | /// Sends the actual request. 35 | pub async fn send(self) -> Result> { 36 | let route = format!("/{}/merges", self.handler.repo); 37 | let post_response = self.handler.crab._post(route, Some(&self)).await?; 38 | 39 | if post_response.status() == http::StatusCode::NO_CONTENT { 40 | return Ok(None); 41 | } 42 | 43 | match FromResponse::from_response(crate::map_github_error(post_response).await?).await { 44 | Ok(res) => Ok(Some(res)), 45 | Err(e) => Err(e), 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/api/repos/pulls.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(serde::Serialize)] 4 | pub struct ListPullsBuilder<'octo, 'r> { 5 | #[serde(skip)] 6 | handler: &'r RepoHandler<'octo>, 7 | #[serde(skip)] 8 | sha: String, 9 | #[serde(skip_serializing_if = "Option::is_none")] 10 | per_page: Option, 11 | #[serde(skip_serializing_if = "Option::is_none")] 12 | page: Option, 13 | } 14 | 15 | impl<'octo, 'r> ListPullsBuilder<'octo, 'r> { 16 | pub fn new(handler: &'r RepoHandler<'octo>, sha: String) -> Self { 17 | Self { 18 | handler, 19 | sha, 20 | per_page: None, 21 | page: None, 22 | } 23 | } 24 | 25 | /// Results per page (max 100). 26 | pub fn per_page(mut self, per_page: impl Into) -> Self { 27 | self.per_page = Some(per_page.into()); 28 | self 29 | } 30 | 31 | /// Page number of the results to fetch. 32 | pub fn page(mut self, page: impl Into) -> Self { 33 | self.page = Some(page.into()); 34 | self 35 | } 36 | 37 | /// Sends the actual request. 38 | pub async fn send(self) -> crate::Result> { 39 | let route = format!("/{}/commits/{sha}/pulls", self.handler.repo, sha = self.sha,); 40 | self.handler.crab.get(route, Some(&self)).await 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/api/repos/stargazers.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(serde::Serialize)] 4 | pub struct ListStarGazersBuilder<'octo, 'r> { 5 | #[serde(skip)] 6 | handler: &'r RepoHandler<'octo>, 7 | #[serde(skip_serializing_if = "Option::is_none")] 8 | per_page: Option, 9 | #[serde(skip_serializing_if = "Option::is_none")] 10 | page: Option, 11 | } 12 | 13 | impl<'octo, 'r> ListStarGazersBuilder<'octo, 'r> { 14 | pub fn new(handler: &'r RepoHandler<'octo>) -> Self { 15 | Self { 16 | handler, 17 | per_page: None, 18 | page: None, 19 | } 20 | } 21 | 22 | /// Results per page (max 100). 23 | pub fn per_page(mut self, per_page: impl Into) -> Self { 24 | self.per_page = Some(per_page.into()); 25 | self 26 | } 27 | 28 | /// Page number of the results to fetch. 29 | pub fn page(mut self, page: impl Into) -> Self { 30 | self.page = Some(page.into()); 31 | self 32 | } 33 | 34 | /// Sends the actual request. 35 | pub async fn send(self) -> crate::Result> { 36 | let route = format!("/{}/stargazers", self.handler.repo); 37 | 38 | let mut headers = http::header::HeaderMap::new(); 39 | headers.insert(ACCEPT, "application/vnd.github.star+json".parse().unwrap()); 40 | 41 | self.handler 42 | .crab 43 | .get_with_headers(route, Some(&self), Some(headers)) 44 | .await 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/api/repos/tags.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(serde::Serialize)] 4 | pub struct ListTagsBuilder<'octo, 'r> { 5 | #[serde(skip)] 6 | handler: &'r RepoHandler<'octo>, 7 | #[serde(skip_serializing_if = "Option::is_none")] 8 | per_page: Option, 9 | #[serde(skip_serializing_if = "Option::is_none")] 10 | page: Option, 11 | } 12 | 13 | impl<'octo, 'r> ListTagsBuilder<'octo, 'r> { 14 | pub fn new(handler: &'r RepoHandler<'octo>) -> Self { 15 | Self { 16 | handler, 17 | per_page: None, 18 | page: None, 19 | } 20 | } 21 | 22 | /// Results per page (max 100). 23 | pub fn per_page(mut self, per_page: impl Into) -> Self { 24 | self.per_page = Some(per_page.into()); 25 | self 26 | } 27 | 28 | /// Page number of the results to fetch. 29 | pub fn page(mut self, page: impl Into) -> Self { 30 | self.page = Some(page.into()); 31 | self 32 | } 33 | 34 | /// Sends the actual request. 35 | pub async fn send(self) -> crate::Result> { 36 | let route = format!("/{}/tags", self.handler.repo); 37 | self.handler.crab.get(route, Some(&self)).await 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/api/repos/teams.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(serde::Serialize)] 4 | pub struct ListTeamsBuilder<'octo, 'r> { 5 | #[serde(skip)] 6 | handler: &'r RepoHandler<'octo>, 7 | #[serde(skip_serializing_if = "Option::is_none")] 8 | per_page: Option, 9 | #[serde(skip_serializing_if = "Option::is_none")] 10 | page: Option, 11 | } 12 | 13 | impl<'octo, 'r> ListTeamsBuilder<'octo, 'r> { 14 | pub fn new(handler: &'r RepoHandler<'octo>) -> Self { 15 | Self { 16 | handler, 17 | per_page: None, 18 | page: None, 19 | } 20 | } 21 | 22 | /// Results per page (max 100). 23 | pub fn per_page(mut self, per_page: impl Into) -> Self { 24 | self.per_page = Some(per_page.into()); 25 | self 26 | } 27 | 28 | /// Page number of the results to fetch. 29 | pub fn page(mut self, page: impl Into) -> Self { 30 | self.page = Some(page.into()); 31 | self 32 | } 33 | 34 | /// Sends the actual request. 35 | pub async fn send(self) -> crate::Result> { 36 | let route = format!("/{}/teams", self.handler.repo); 37 | self.handler.crab.get(route, Some(&self)).await 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/api/teams/children.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::{models, Page, Result}; 3 | 4 | #[derive(serde::Serialize)] 5 | pub struct ListChildTeamsBuilder<'octo, 'r> { 6 | #[serde(skip)] 7 | handler: &'r TeamHandler<'octo>, 8 | #[serde(skip)] 9 | slug: String, 10 | #[serde(skip_serializing_if = "Option::is_none")] 11 | per_page: Option, 12 | #[serde(skip_serializing_if = "Option::is_none")] 13 | page: Option, 14 | } 15 | 16 | impl<'octo, 'r> ListChildTeamsBuilder<'octo, 'r> { 17 | pub(crate) fn new(handler: &'r TeamHandler<'octo>, slug: String) -> Self { 18 | Self { 19 | handler, 20 | slug, 21 | per_page: None, 22 | page: None, 23 | } 24 | } 25 | 26 | /// Results per page. 27 | pub fn per_page(mut self, per_page: impl Into) -> Self { 28 | self.per_page = Some(per_page.into()); 29 | self 30 | } 31 | 32 | /// Page number of the results to fetch. 33 | pub fn page(mut self, page: impl Into) -> Self { 34 | self.page = Some(page.into()); 35 | self 36 | } 37 | 38 | /// Sends the actual request. 39 | pub async fn send(self) -> Result> { 40 | let route = format!( 41 | "/orgs/{org}/teams/{team}/teams", 42 | org = self.handler.owner, 43 | team = self.slug, 44 | ); 45 | self.handler.crab.get(route, Some(&self)).await 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/api/teams/invitations.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::{models::teams, Page, Result}; 3 | 4 | #[derive(serde::Serialize)] 5 | pub struct ListTeamInvitationsBuilder<'octo, 'r> { 6 | #[serde(skip)] 7 | handler: &'r TeamHandler<'octo>, 8 | #[serde(skip)] 9 | slug: String, 10 | #[serde(skip_serializing_if = "Option::is_none")] 11 | per_page: Option, 12 | #[serde(skip_serializing_if = "Option::is_none")] 13 | page: Option, 14 | } 15 | 16 | impl<'octo, 'r> ListTeamInvitationsBuilder<'octo, 'r> { 17 | pub(crate) fn new(handler: &'r TeamHandler<'octo>, slug: String) -> Self { 18 | Self { 19 | handler, 20 | slug, 21 | per_page: None, 22 | page: None, 23 | } 24 | } 25 | 26 | /// Results per page. 27 | pub fn per_page(mut self, per_page: impl Into) -> Self { 28 | self.per_page = Some(per_page.into()); 29 | self 30 | } 31 | 32 | /// Page number of the results to fetch. 33 | pub fn page(mut self, page: impl Into) -> Self { 34 | self.page = Some(page.into()); 35 | self 36 | } 37 | 38 | /// Sends the actual request. 39 | pub async fn send(self) -> Result> { 40 | let route = format!( 41 | "/orgs/{org}/teams/{team}/invitations", 42 | org = self.handler.owner, 43 | team = self.slug, 44 | ); 45 | self.handler.crab.get(route, Some(&self)).await 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/api/teams/list.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::{models, Page, Result}; 3 | 4 | #[derive(serde::Serialize)] 5 | pub struct ListTeamsBuilder<'octo, 'r> { 6 | #[serde(skip)] 7 | handler: &'r TeamHandler<'octo>, 8 | #[serde(skip_serializing_if = "Option::is_none")] 9 | per_page: Option, 10 | #[serde(skip_serializing_if = "Option::is_none")] 11 | page: Option, 12 | } 13 | 14 | impl<'octo, 'r> ListTeamsBuilder<'octo, 'r> { 15 | pub(crate) fn new(handler: &'r TeamHandler<'octo>) -> Self { 16 | Self { 17 | handler, 18 | per_page: None, 19 | page: None, 20 | } 21 | } 22 | 23 | /// Results per page. 24 | pub fn per_page(mut self, per_page: impl Into) -> Self { 25 | self.per_page = Some(per_page.into()); 26 | self 27 | } 28 | 29 | /// Page number of the results to fetch. 30 | pub fn page(mut self, page: impl Into) -> Self { 31 | self.page = Some(page.into()); 32 | self 33 | } 34 | 35 | /// Sends the actual request. 36 | pub async fn send(self) -> Result> { 37 | let route = format!("/orgs/{owner}/teams", owner = self.handler.owner); 38 | self.handler.crab.get(route, Some(&self)).await 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/api/teams/members.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::{models, Page, Result}; 3 | 4 | #[derive(serde::Serialize)] 5 | pub struct ListTeamMembersBuilder<'octo, 'r> { 6 | #[serde(skip)] 7 | handler: &'r TeamHandler<'octo>, 8 | #[serde(skip)] 9 | slug: String, 10 | #[serde(skip_serializing_if = "Option::is_none")] 11 | per_page: Option, 12 | #[serde(skip_serializing_if = "Option::is_none")] 13 | page: Option, 14 | } 15 | 16 | impl<'octo, 'r> ListTeamMembersBuilder<'octo, 'r> { 17 | pub(crate) fn new(handler: &'r TeamHandler<'octo>, slug: String) -> Self { 18 | Self { 19 | handler, 20 | slug, 21 | per_page: None, 22 | page: None, 23 | } 24 | } 25 | 26 | /// Results per page. 27 | pub fn per_page(mut self, per_page: impl Into) -> Self { 28 | self.per_page = Some(per_page.into()); 29 | self 30 | } 31 | 32 | /// Page number of the results to fetch. 33 | pub fn page(mut self, page: impl Into) -> Self { 34 | self.page = Some(page.into()); 35 | self 36 | } 37 | 38 | /// Sends the actual request. 39 | pub async fn send(self) -> Result> { 40 | let route = format!( 41 | "/orgs/{org}/teams/{team}/members", 42 | org = self.handler.owner, 43 | team = self.slug, 44 | ); 45 | self.handler.crab.get(route, Some(&self)).await 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/from_response.rs: -------------------------------------------------------------------------------- 1 | use bytes::Bytes; 2 | use http_body::Body; 3 | use http_body_util::BodyExt; 4 | use snafu::ResultExt; 5 | 6 | /// A trait for mapping from a `http::Response` to an another type. 7 | #[async_trait::async_trait] 8 | pub trait FromResponse: Sized { 9 | async fn from_response(response: http::Response) -> crate::Result 10 | where 11 | B: Body + Send; 12 | } 13 | 14 | #[async_trait::async_trait] 15 | impl FromResponse for T { 16 | async fn from_response(response: http::Response) -> crate::Result 17 | where 18 | B: Body + Send, 19 | { 20 | let (_, body) = response.into_parts(); 21 | let body = body.collect().await?.to_bytes(); 22 | let de = &mut serde_json::Deserializer::from_slice(&body); 23 | return serde_path_to_error::deserialize(de).context(crate::error::JsonSnafu); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/models/actions.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct SelfHostedRunner { 6 | pub id: RunnerId, 7 | #[serde(skip_serializing_if = "Option::is_none")] 8 | pub runner_group_id: Option, 9 | pub name: String, 10 | pub os: String, 11 | pub status: String, 12 | pub busy: bool, 13 | pub labels: Vec, 14 | } 15 | 16 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 17 | #[non_exhaustive] 18 | pub struct SelfHostedRunnerLabel { 19 | pub id: RunnerLabelId, 20 | pub name: String, 21 | #[serde(rename = "type")] 22 | pub label_type: SelfHostedRunnerLabelType, 23 | } 24 | 25 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 26 | #[serde(rename_all = "kebab-case")] 27 | pub enum SelfHostedRunnerLabelType { 28 | ReadOnly, 29 | Custom, 30 | } 31 | 32 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 33 | #[non_exhaustive] 34 | pub struct SelfHostedRunnerJitConfig { 35 | pub runner: SelfHostedRunner, 36 | pub encoded_jit_config: String, 37 | } 38 | 39 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 40 | #[non_exhaustive] 41 | pub struct SelfHostedRunnerToken { 42 | pub token: String, 43 | pub expires_at: DateTime, 44 | } 45 | -------------------------------------------------------------------------------- /src/models/activity.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct Notification { 6 | pub id: NotificationId, 7 | pub repository: Repository, 8 | pub subject: Subject, 9 | pub reason: String, 10 | pub unread: bool, 11 | pub updated_at: chrono::DateTime, 12 | pub last_read_at: Option>, 13 | pub url: Url, 14 | } 15 | 16 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 17 | #[serde(rename_all = "lowercase")] 18 | #[non_exhaustive] 19 | pub enum Reason { 20 | Assign, 21 | Author, 22 | Comment, 23 | Invitation, 24 | Manual, 25 | Mention, 26 | #[serde(rename = "review_requested")] 27 | ReviewRequested, 28 | #[serde(rename = "security_alert")] 29 | SecurityAlert, 30 | #[serde(rename = "state_change")] 31 | StateChange, 32 | Subscribed, 33 | #[serde(rename = "team_mention")] 34 | TeamMention, 35 | } 36 | 37 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 38 | #[non_exhaustive] 39 | pub struct Subject { 40 | pub title: String, 41 | pub url: Option, 42 | pub latest_comment_url: Option, 43 | pub r#type: String, 44 | } 45 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 46 | #[non_exhaustive] 47 | pub struct ThreadSubscription { 48 | pub subscribed: bool, 49 | pub ignored: bool, 50 | pub reason: Option, 51 | pub created_at: chrono::DateTime, 52 | pub url: Url, 53 | pub thread_url: Url, 54 | } 55 | -------------------------------------------------------------------------------- /src/models/events/payload/commit_comment.rs: -------------------------------------------------------------------------------- 1 | use crate::models::issues::Comment; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | /// The payload in a [`super::EventPayload::CommitCommentEvent`] type. 5 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 6 | #[non_exhaustive] 7 | pub struct CommitCommentEventPayload { 8 | /// The comment this event corresponds to. 9 | pub comment: Comment, 10 | } 11 | 12 | #[cfg(test)] 13 | mod test { 14 | use crate::models::events::{payload::EventPayload, Event}; 15 | 16 | #[test] 17 | fn should_deserialize_with_correct_payload() { 18 | let json = include_str!("../../../../tests/resources/commit_comment_event.json"); 19 | let event: Event = serde_json::from_str(json).unwrap(); 20 | if let Some(EventPayload::CommitCommentEvent(ref payload)) = 21 | event.payload.as_ref().unwrap().specific 22 | { 23 | assert_eq!(payload.comment.id.0, 46377107); 24 | } else { 25 | panic!("unexpected event payload encountered: {:#?}", event.payload); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/models/events/payload/delete.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | /// The payload in a [`super::EventPayload::DeleteEvent`] type. 4 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 5 | #[non_exhaustive] 6 | pub struct DeleteEventPayload { 7 | /// The ref which was deleted. 8 | pub r#ref: String, 9 | /// The type of the ref which was deleted. 10 | pub ref_type: String, 11 | } 12 | 13 | #[cfg(test)] 14 | mod test { 15 | use crate::models::events::{payload::EventPayload, Event}; 16 | 17 | #[test] 18 | fn should_deserialize_with_correct_payload() { 19 | let json = include_str!("../../../../tests/resources/delete_event.json"); 20 | let event: Event = serde_json::from_str(json).unwrap(); 21 | if let Some(EventPayload::DeleteEvent(ref payload)) = 22 | event.payload.as_ref().unwrap().specific 23 | { 24 | assert_eq!(payload.r#ref, "test2"); 25 | assert_eq!(payload.ref_type, "branch"); 26 | } else { 27 | panic!("unexpected event payload encountered: {:#?}", event.payload); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/models/events/payload/fork.rs: -------------------------------------------------------------------------------- 1 | use crate::models::Repository; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | /// The payload in a [`super::EventPayload::ForkEvent`] type. 5 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 6 | #[non_exhaustive] 7 | pub struct ForkEventPayload { 8 | /// The fork. 9 | pub forkee: Repository, 10 | } 11 | 12 | #[cfg(test)] 13 | mod test { 14 | use crate::models::events::{payload::EventPayload, Event}; 15 | 16 | #[test] 17 | fn should_deserialize_with_correct_payload() { 18 | let json = include_str!("../../../../tests/resources/fork_event.json"); 19 | let event: Event = serde_json::from_str(json).unwrap(); 20 | if let Some(EventPayload::ForkEvent(ref payload)) = event.payload.as_ref().unwrap().specific 21 | { 22 | assert_eq!(payload.forkee.id.0, 334843423); 23 | } else { 24 | panic!("unexpected event payload encountered: {:#?}", event.payload); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/models/events/payload/installation.rs: -------------------------------------------------------------------------------- 1 | //! This event occurs when there is activity relating to a GitHub App 2 | //! installation. All GitHub Apps receive this event by default. You cannot 3 | //! manually subscribe to this event. 4 | 5 | use serde::{Deserialize, Serialize}; 6 | 7 | use super::InstallationEventRepository; 8 | use crate::models::Author; 9 | 10 | /// The payload in a webhook installation event type. 11 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 12 | #[non_exhaustive] 13 | pub struct InstallationEventPayload { 14 | /// The action this event represents. 15 | pub action: InstallationEventAction, 16 | /// An enterprise on GitHub 17 | pub enterprise: Option, 18 | /// An array of repositories that the installation can access 19 | pub repositories: Vec, 20 | /// The initiator of the request, mainly for the [`created`](crate::models::events::payload::InstallationEventAction::Created) action 21 | pub requester: Option, 22 | } 23 | 24 | /// The action on an installation this event corresponds to. 25 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 26 | #[serde(rename_all = "snake_case")] 27 | #[non_exhaustive] 28 | pub enum InstallationEventAction { 29 | /// Someone installed a GitHub App on a user or organization account. 30 | Created, 31 | /// Someone uninstalled a GitHub App on a user or organization account. 32 | Deleted, 33 | /// Someone granted new permissions to a GitHub App. 34 | NewPermissionsAccepted, 35 | /// Someone blocked access by a GitHub App to their user or organization account. 36 | Suspend, 37 | /// A GitHub App that was blocked from accessing a user or organization account was given access the account again. 38 | Unsuspend, 39 | } 40 | -------------------------------------------------------------------------------- /src/models/events/payload/installation_repositories.rs: -------------------------------------------------------------------------------- 1 | //! This event occurs when there is activity relating to which repositories a 2 | //! GitHub App installation can access. All GitHub Apps receive this event by 3 | //! default. You cannot manually subscribe to this event. 4 | 5 | use serde::{Deserialize, Serialize}; 6 | 7 | use super::InstallationEventRepository; 8 | use crate::models::Author; 9 | 10 | /// The payload in a webhook installation_repositories event type. 11 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 12 | #[non_exhaustive] 13 | pub struct InstallationRepositoriesEventPayload { 14 | /// The action this event represents. 15 | pub action: InstallationRepositoriesEventAction, 16 | /// An enterprise on GitHub 17 | pub enterprise: Option, 18 | /// An array of repositories, which were added to the installation 19 | pub repositories_added: Vec, 20 | /// An array of repositories, which were removed from the installation 21 | pub repositories_removed: Vec, 22 | /// Describe whether all repositories have been selected or there's a selection involved 23 | pub repository_selection: InstallationRepositoriesEventSelection, 24 | /// The initiator of the request, mainly for the [`created`](crate::models::events::payload::InstallationEventAction::Created) action 25 | pub requester: Option, 26 | } 27 | 28 | /// The action on an installation this event corresponds to. 29 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 30 | #[serde(rename_all = "snake_case")] 31 | #[non_exhaustive] 32 | pub enum InstallationRepositoriesEventAction { 33 | /// A GitHub App installation was granted access to one or more repositories. 34 | Added, 35 | /// Access to one or more repositories was revoked for a GitHub App installation. 36 | Removed, 37 | } 38 | 39 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 40 | #[serde(rename_all = "snake_case")] 41 | #[non_exhaustive] 42 | pub enum InstallationRepositoriesEventSelection { 43 | All, 44 | Selected, 45 | } 46 | -------------------------------------------------------------------------------- /src/models/events/payload/installation_target.rs: -------------------------------------------------------------------------------- 1 | //! This event occurs when there is activity relating to the user or 2 | //! organization account that a GitHub App is installed on. 3 | 4 | use serde::{Deserialize, Serialize}; 5 | 6 | use crate::models::orgs::Organization; 7 | 8 | /// The payload in a webhook installation_target event type. 9 | /// 10 | /// Somebody renamed the user or organization account that a GitHub App is installed on. 11 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 12 | #[non_exhaustive] 13 | pub struct InstallationTargetEventPayload { 14 | pub account: Organization, 15 | pub changes: InstallationTargetChanges, 16 | pub target_type: String, 17 | } 18 | 19 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 20 | #[non_exhaustive] 21 | pub struct InstallationTargetChanges { 22 | pub login: InstallationTargetLoginChanges, 23 | pub slug: InstallationTargetSlugChanges, 24 | } 25 | 26 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 27 | #[non_exhaustive] 28 | pub struct InstallationTargetLoginChanges { 29 | pub from: String, 30 | } 31 | 32 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 33 | #[non_exhaustive] 34 | pub struct InstallationTargetSlugChanges { 35 | pub from: String, 36 | } 37 | -------------------------------------------------------------------------------- /src/models/events/payload/public.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | /// The payload in a [`super::EventPayload::PublicEvent`] type. 4 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 5 | #[non_exhaustive] 6 | pub struct PublicEventPayload {} 7 | -------------------------------------------------------------------------------- /src/models/events/payload/watch.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | /// The payload in a [`super::EventPayload::WatchEvent`] type. 4 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 5 | #[non_exhaustive] 6 | pub struct WatchEventPayload { 7 | /// The action that was performed. 8 | pub action: WatchEventAction, 9 | } 10 | 11 | /// The action that was performed as part of the [`super::EventPayload::WatchEvent`]. 12 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 13 | #[serde(rename_all = "snake_case")] 14 | #[non_exhaustive] 15 | pub enum WatchEventAction { 16 | Started, 17 | } 18 | 19 | #[cfg(test)] 20 | mod test { 21 | use crate::models::events::{ 22 | payload::{EventPayload, WatchEventAction}, 23 | Event, 24 | }; 25 | 26 | #[test] 27 | fn should_deserialize_with_correct_payload() { 28 | let json = include_str!("../../../../tests/resources/watch_event.json"); 29 | let event: Event = serde_json::from_str(json).unwrap(); 30 | if let Some(EventPayload::WatchEvent(ref payload)) = 31 | event.payload.as_ref().unwrap().specific 32 | { 33 | assert_eq!(payload.action, WatchEventAction::Started); 34 | } else { 35 | panic!("unexpected event payload encountered: {:#?}", event.payload); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/models/events/payload/workflow_run.rs: -------------------------------------------------------------------------------- 1 | use crate::models::workflows::{Run, WorkFlow}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | /// The payload in a [`super::EventPayload::WorkflowRunEvent`] type. 5 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 6 | #[non_exhaustive] 7 | pub struct WorkflowRunEventPayload { 8 | pub action: WorkflowRunEventAction, 9 | pub workflow_run: Run, 10 | pub workflow: WorkFlow, 11 | } 12 | 13 | /// The action on a pull request this event corresponds to. 14 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 15 | #[serde(rename_all = "snake_case")] 16 | #[non_exhaustive] 17 | pub enum WorkflowRunEventAction { 18 | Requested, 19 | InProgress, 20 | Completed, 21 | } 22 | 23 | #[cfg(test)] 24 | mod test { 25 | use crate::models::events::{payload::EventPayload, Event}; 26 | 27 | #[test] 28 | fn should_deserialize_with_correct_payload() { 29 | let json = include_str!("../../../../tests/resources/workflow_run_event.json"); 30 | let event: Event = serde_json::from_str(json).unwrap(); 31 | if let Some(EventPayload::WorkflowRunEvent(ref payload)) = 32 | event.payload.as_ref().unwrap().specific 33 | { 34 | assert_eq!(payload.workflow_run.run_number, 1185); 35 | } else { 36 | panic!("unexpected event payload encountered: {:#?}", event.payload); 37 | } 38 | } 39 | 40 | #[test] 41 | fn should_deserialize_with_correct_payload_with_no_org_present() { 42 | let json = 43 | include_str!("../../../../tests/resources/workflow_run_event_no_organization.json"); 44 | let event: Event = serde_json::from_str(json).unwrap(); 45 | if let Some(EventPayload::WorkflowRunEvent(ref payload)) = 46 | event.payload.as_ref().unwrap().specific 47 | { 48 | assert_eq!(payload.workflow_run.run_number, 1185); 49 | assert_eq!(event.payload.as_ref().unwrap().organization, None); 50 | } else { 51 | panic!("unexpected event payload encountered: {:#?}", event.payload); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/models/gists.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use std::collections::BTreeMap; 3 | 4 | #[non_exhaustive] 5 | #[derive(Debug, Deserialize)] 6 | pub struct Gist { 7 | pub comments: u64, 8 | pub comments_url: Url, 9 | pub commits_url: Url, 10 | pub created_at: DateTime, 11 | pub description: Option, 12 | pub files: BTreeMap, 13 | pub forks_url: Url, 14 | pub git_pull_url: Url, 15 | pub git_push_url: Url, 16 | pub html_url: Url, 17 | pub id: String, 18 | pub node_id: String, 19 | pub public: bool, 20 | pub updated_at: DateTime, 21 | pub url: Url, 22 | } 23 | 24 | #[non_exhaustive] 25 | #[derive(Debug, Deserialize)] 26 | pub struct GistFile { 27 | pub content: Option, 28 | pub filename: String, 29 | pub language: Option, 30 | pub r#type: String, 31 | pub raw_url: Url, 32 | pub size: u64, 33 | pub truncated: Option, 34 | } 35 | 36 | #[non_exhaustive] 37 | #[derive(Debug, Deserialize)] 38 | pub struct GistCommit { 39 | pub user: Option, 40 | pub version: String, 41 | pub committed_at: DateTime, 42 | pub change_status: GistChangeStatus, 43 | pub url: Url, 44 | } 45 | 46 | #[non_exhaustive] 47 | #[derive(Debug, Deserialize)] 48 | pub struct GistChangeStatus { 49 | pub total: Option, 50 | pub additions: Option, 51 | pub deletions: Option, 52 | } 53 | 54 | #[non_exhaustive] 55 | #[derive(Debug, Deserialize)] 56 | pub struct GistRevision { 57 | pub id: String, 58 | pub node_id: String, 59 | pub public: bool, 60 | pub created_at: DateTime, 61 | pub updated_at: DateTime, 62 | pub description: Option, 63 | pub files: BTreeMap, 64 | pub url: Url, 65 | } 66 | -------------------------------------------------------------------------------- /src/models/orgs/secrets.rs: -------------------------------------------------------------------------------- 1 | use super::super::*; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[serde(rename_all = "snake_case")] 5 | pub enum Visibility { 6 | All, 7 | Private, 8 | Selected, 9 | } 10 | 11 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 12 | pub struct OrganizationSecret { 13 | pub name: String, 14 | pub created_at: DateTime, 15 | pub updated_at: DateTime, 16 | pub visibility: Visibility, 17 | #[serde(skip_serializing_if = "Option::is_none")] 18 | pub selected_repositories_url: Option, 19 | } 20 | 21 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 22 | #[non_exhaustive] 23 | pub struct OrganizationSecrets { 24 | pub total_count: i32, 25 | pub secrets: Vec, 26 | } 27 | 28 | #[derive(Debug, Clone, PartialEq, Serialize)] 29 | pub struct CreateOrganizationSecret<'a> { 30 | /// Value for your secret, 31 | /// encrypted with LibSodium using the public key retrieved from the Get an organization public key endpoint. 32 | pub encrypted_value: &'a str, 33 | /// ID of the key you used to encrypt the secret. 34 | pub key_id: &'a str, 35 | /// Which type of organization repositories have access to the organization secret. 36 | pub visibility: Visibility, 37 | /// An array of repository ids that can access the organization secret. 38 | /// You can only provide a list of repository ids when the visibility is set to selected. 39 | #[serde(skip_serializing_if = "Option::is_none")] 40 | pub selected_repository_ids: Option<&'a [u32]>, 41 | } 42 | 43 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 44 | #[serde(rename_all = "snake_case")] 45 | pub enum CreateOrganizationSecretResponse { 46 | Created, 47 | Updated, 48 | } 49 | -------------------------------------------------------------------------------- /src/models/reactions.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)] 4 | pub enum ReactionContent { 5 | #[serde(rename = "heart")] 6 | Heart, 7 | #[serde(rename = "+1")] 8 | PlusOne, 9 | #[serde(rename = "laugh")] 10 | Laugh, 11 | #[serde(rename = "confused")] 12 | Confused, 13 | #[serde(rename = "hooray")] 14 | Hooray, 15 | #[serde(rename = "-1")] 16 | MinusOne, 17 | #[serde(rename = "rocket")] 18 | Rocket, 19 | #[serde(rename = "eyes")] 20 | Eyes, 21 | } 22 | 23 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 24 | #[non_exhaustive] 25 | pub struct Reaction { 26 | pub id: ReactionId, 27 | pub node_id: String, 28 | pub user: Author, 29 | pub content: ReactionContent, 30 | pub created_at: chrono::DateTime, 31 | } 32 | -------------------------------------------------------------------------------- /src/models/repos/secrets.rs: -------------------------------------------------------------------------------- 1 | use super::super::*; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | pub struct RepositorySecret { 5 | pub name: String, 6 | pub created_at: DateTime, 7 | pub updated_at: DateTime, 8 | } 9 | 10 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 11 | #[non_exhaustive] 12 | pub struct RepositorySecrets { 13 | pub total_count: i32, 14 | pub secrets: Vec, 15 | } 16 | 17 | #[derive(Debug, Clone, PartialEq, Serialize)] 18 | pub struct CreateRepositorySecret<'a> { 19 | /// Value for your secret, 20 | /// encrypted with LibSodium using the public key retrieved from the Get an organization public key endpoint. 21 | pub encrypted_value: &'a str, 22 | /// ID of the key you used to encrypt the secret. 23 | pub key_id: &'a str, 24 | } 25 | 26 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 27 | #[serde(rename_all = "snake_case")] 28 | pub enum CreateRepositorySecretResponse { 29 | Created, 30 | Updated, 31 | } 32 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/check_run.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct CheckRunWebhookEventPayload { 6 | pub action: CheckRunWebhookEventAction, 7 | pub check_run: serde_json::Value, 8 | } 9 | 10 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 11 | #[serde(rename_all = "snake_case")] 12 | #[non_exhaustive] 13 | pub enum CheckRunWebhookEventAction { 14 | Completed, 15 | Created, 16 | RequestedAction, 17 | Rerequested, 18 | } 19 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/check_suite.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct CheckSuiteWebhookEventPayload { 6 | pub action: CheckSuiteWebhookEventAction, 7 | pub enterprise: Option, 8 | pub check_suite: serde_json::Value, 9 | } 10 | 11 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 12 | #[serde(rename_all = "snake_case")] 13 | #[non_exhaustive] 14 | pub enum CheckSuiteWebhookEventAction { 15 | Completed, 16 | Requested, 17 | Rerequested, 18 | } 19 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/code_scanning_alert.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use crate::models::{code_scannings::CodeScanningAlert, orgs::Organization, Author, Repository}; 4 | 5 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 6 | #[non_exhaustive] 7 | pub struct CodeScanningAlertWebhookEventPayload { 8 | /// The action that was performed. 9 | pub action: CodeScanningAlertWebhookEventAction, 10 | /// The code scanning alert that was affected. 11 | pub alert: CodeScanningAlert, 12 | /// The commit SHA of the code scanning alert. When the action is reopened_by_user or closed_by_user, the event was triggered by the sender and this value will be empty. 13 | pub commit_oid: String, 14 | #[serde(skip_serializing_if = "Option::is_none")] 15 | pub enterprise: Option, 16 | #[serde(skip_serializing_if = "Option::is_none")] 17 | pub organization: Option, 18 | /// The Git reference of the code scanning alert. When the action is reopened_by_user or closed_by_user, the event was triggered by the sender and this value will be empty. 19 | pub r#ref: String, 20 | /// The repository that the code scanning alert belongs to. 21 | pub repository: Repository, 22 | /// The user that triggered the code scanning alert. 23 | pub sender: Author, 24 | } 25 | 26 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 27 | #[serde(rename_all = "snake_case")] 28 | #[non_exhaustive] 29 | pub enum CodeScanningAlertWebhookEventAction { 30 | AppearedInBranch, 31 | ClosedByUser, 32 | Created, 33 | Fixed, 34 | Reopened, 35 | ReopenedByUser, 36 | } 37 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/commit_comment.rs: -------------------------------------------------------------------------------- 1 | use crate::models::commits::Comment; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 5 | #[non_exhaustive] 6 | pub struct CommitCommentWebhookEventPayload { 7 | pub action: CommitCommentWebhookEventAction, 8 | pub comment: Comment, 9 | } 10 | 11 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 12 | #[serde(rename_all = "snake_case")] 13 | #[non_exhaustive] 14 | pub enum CommitCommentWebhookEventAction { 15 | Created, 16 | } 17 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/create.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use super::{PusherType, RefType}; 4 | 5 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 6 | #[non_exhaustive] 7 | pub struct CreateWebhookEventPayload { 8 | pub description: Option, 9 | pub enterprise: Option, 10 | pub master_branch: String, 11 | pub pusher_type: PusherType, 12 | pub r#ref: String, 13 | pub ref_type: RefType, 14 | } 15 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/delete.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use super::{PusherType, RefType}; 4 | 5 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 6 | #[non_exhaustive] 7 | pub struct DeleteWebhookEventPayload { 8 | pub enterprise: Option, 9 | pub pusher_type: PusherType, 10 | pub r#ref: String, 11 | pub ref_type: RefType, 12 | } 13 | 14 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 15 | #[serde(rename_all = "snake_case")] 16 | #[non_exhaustive] 17 | pub enum DeleteWebhookEventAction { 18 | Created, 19 | Deleted, 20 | Edited, 21 | } 22 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/dependabot_alert.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct DependabotAlertWebhookEventPayload { 6 | pub action: DependabotAlertWebhookEventAction, 7 | pub alert: serde_json::Value, 8 | pub enterprise: Option, 9 | } 10 | 11 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 12 | #[serde(rename_all = "snake_case")] 13 | #[non_exhaustive] 14 | pub enum DependabotAlertWebhookEventAction { 15 | AutoDismissed, 16 | AutoReopened, 17 | Created, 18 | Dismissed, 19 | Fixed, 20 | Reintroduced, 21 | Reopened, 22 | } 23 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/deploy_key.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct DeployKeyWebhookEventPayload { 6 | pub action: DeployKeyWebhookEventAction, 7 | pub enterprise: Option, 8 | pub key: serde_json::Value, 9 | } 10 | 11 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 12 | #[serde(rename_all = "snake_case")] 13 | #[non_exhaustive] 14 | pub enum DeployKeyWebhookEventAction { 15 | Created, 16 | Deleted, 17 | } 18 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/deployment.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct DeploymentWebhookEventPayload { 6 | pub action: DeploymentWebhookEventAction, 7 | pub deployment: serde_json::Value, 8 | pub enterprise: Option, 9 | pub workflow: serde_json::Value, 10 | pub workflow_run: serde_json::Value, 11 | } 12 | 13 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 14 | #[serde(rename_all = "snake_case")] 15 | #[non_exhaustive] 16 | pub enum DeploymentWebhookEventAction { 17 | Created, 18 | } 19 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/deployment_protection_rule.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct DeploymentProtectionRuleWebhookEventPayload { 6 | pub action: DeploymentProtectionRuleWebhookEventAction, 7 | pub environment: Option, 8 | pub event: Option, 9 | pub deployment_callback_url: Option, 10 | pub deployment: Option, 11 | pub pull_requests: Option>, 12 | } 13 | 14 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 15 | #[serde(rename_all = "snake_case")] 16 | #[non_exhaustive] 17 | pub enum DeploymentProtectionRuleWebhookEventAction { 18 | Requested, 19 | } 20 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/deployment_status.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct DeploymentStatusWebhookEventPayload { 6 | pub action: DeploymentStatusWebhookEventAction, 7 | pub check_run: Option, 8 | pub deployment: serde_json::Value, 9 | pub deployment_status: serde_json::Value, 10 | pub enterprise: Option, 11 | pub workflow: Option, 12 | pub workflow_run: Option, 13 | } 14 | 15 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 16 | #[serde(rename_all = "snake_case")] 17 | #[non_exhaustive] 18 | pub enum DeploymentStatusWebhookEventAction { 19 | Created, 20 | } 21 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/discussion.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct DiscussionWebhookEventPayload { 6 | pub action: DiscussionWebhookEventAction, 7 | pub answer: Option, 8 | pub discussion: serde_json::Value, 9 | pub enterprise: Option, 10 | pub changes: Option, 11 | pub label: Option, 12 | } 13 | 14 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 15 | #[serde(rename_all = "snake_case")] 16 | #[non_exhaustive] 17 | pub enum DiscussionWebhookEventAction { 18 | Answered, 19 | CategoryChanged, 20 | Closed, 21 | Created, 22 | Deleted, 23 | Edited, 24 | Labeled, 25 | Locked, 26 | Pinned, 27 | Reopened, 28 | Transferred, 29 | Unanswered, 30 | Unlabeled, 31 | Unlocked, 32 | Unpinned, 33 | } 34 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/discussion_comment.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct DiscussionCommentWebhookEventPayload { 6 | pub action: DiscussionCommentWebhookEventAction, 7 | pub changes: Option, 8 | pub comment: serde_json::Value, 9 | pub discussion: serde_json::Value, 10 | pub enterprise: Option, 11 | } 12 | 13 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 14 | #[serde(rename_all = "snake_case")] 15 | #[non_exhaustive] 16 | pub enum DiscussionCommentWebhookEventAction { 17 | Created, 18 | Deleted, 19 | Edited, 20 | } 21 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/fork.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use crate::models::Repository; 4 | 5 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 6 | #[non_exhaustive] 7 | pub struct ForkWebhookEventPayload { 8 | // TODO: Make sure that it's a crate::models::Repository 9 | pub forkee: Repository, 10 | pub enterprise: Option, 11 | } 12 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/github_app_authorization.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct GithubAppAuthorizationWebhookEventPayload { 6 | pub action: GithubAppAuthorizationWebhookEventAction, 7 | pub enterprise: Option, 8 | } 9 | 10 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 11 | #[serde(rename_all = "snake_case")] 12 | #[non_exhaustive] 13 | pub enum GithubAppAuthorizationWebhookEventAction { 14 | Revoked, 15 | } 16 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/gollum.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct GollumWebhookEventPayload { 6 | pub enterprise: Option, 7 | /// The pages that were updated 8 | pub pages: Vec, 9 | } 10 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/installation.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use crate::models::webhook_events::InstallationEventRepository; 4 | 5 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 6 | #[non_exhaustive] 7 | pub struct InstallationWebhookEventPayload { 8 | pub action: InstallationWebhookEventAction, 9 | pub enterprise: Option, 10 | #[serde(default)] 11 | pub repositories: Option>, 12 | pub requester: Option, 13 | } 14 | 15 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 16 | #[serde(rename_all = "snake_case")] 17 | #[non_exhaustive] 18 | pub enum InstallationWebhookEventAction { 19 | Created, 20 | Deleted, 21 | NewPermissionsAccepted, 22 | Suspend, 23 | Unsuspend, 24 | } 25 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/installation_repositories.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use crate::models::webhook_events::InstallationEventRepository; 4 | 5 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 6 | #[non_exhaustive] 7 | pub struct InstallationRepositoriesWebhookEventPayload { 8 | pub action: InstallationRepositoriesWebhookEventAction, 9 | pub enterprise: Option, 10 | pub repositories_added: Vec, 11 | pub repositories_removed: Vec, 12 | pub repository_selection: InstallationRepositoriesWebhookEventSelection, 13 | pub requester: Option, 14 | } 15 | 16 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 17 | #[serde(rename_all = "snake_case")] 18 | #[non_exhaustive] 19 | pub enum InstallationRepositoriesWebhookEventAction { 20 | Added, 21 | Removed, 22 | } 23 | 24 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 25 | #[serde(rename_all = "snake_case")] 26 | #[non_exhaustive] 27 | pub enum InstallationRepositoriesWebhookEventSelection { 28 | All, 29 | Selected, 30 | } 31 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/installation_target.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 4 | #[non_exhaustive] 5 | pub struct InstallationTargetWebhookEventPayload { 6 | pub account: serde_json::Value, 7 | pub action: String, 8 | pub changes: serde_json::Value, 9 | pub enterprise: Option, 10 | pub target_type: String, 11 | } 12 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/issue_comment.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use crate::models::issues::{Comment, Issue}; 4 | 5 | use super::OldValue; 6 | 7 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 8 | #[non_exhaustive] 9 | pub struct IssueCommentWebhookEventPayload { 10 | pub action: IssueCommentWebhookEventAction, 11 | pub changes: Option, 12 | pub comment: Comment, 13 | pub enterprise: Option, 14 | pub issue: Issue, 15 | } 16 | 17 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 18 | #[serde(rename_all = "snake_case")] 19 | #[non_exhaustive] 20 | pub enum IssueCommentWebhookEventAction { 21 | Created, 22 | Deleted, 23 | Edited, 24 | } 25 | 26 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 27 | #[non_exhaustive] 28 | pub struct IssueCommentWebhookEventChanges { 29 | pub body: OldValue, 30 | } 31 | -------------------------------------------------------------------------------- /src/models/webhook_events/payload/issues.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use crate::models::{issues::Issue, Author, Label, Milestone}; 4 | 5 | use super::OldValue; 6 | 7 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 8 | #[non_exhaustive] 9 | pub struct IssuesWebhookEventPayload { 10 | pub action: IssuesWebhookEventAction, 11 | pub assignee: Option, 12 | pub enterprise: Option, 13 | pub issue: Issue, 14 | pub milestone: Option, 15 | pub label: Option