{"id":13862567,"url":"https://github.com/googlecodelabs/analyze_gsimg","last_synced_at":"2026-01-30T14:59:53.613Z","repository":{"id":149200452,"uuid":"261826163","full_name":"googlecodelabs/analyze_gsimg","owner":"googlecodelabs","description":"Repo for cloud image processing workflow codelab (uses Google Drive, Cloud Storage, Cloud Vision, Sheets)","archived":false,"fork":false,"pushed_at":"2021-12-31T09:02:43.000Z","size":37,"stargazers_count":8,"open_issues_count":0,"forks_count":6,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-07-14T14:03:56.085Z","etag":null,"topics":["authentication","authorization","authorization-scheme","cloud-apis","cloud-storage","cloud-vision","codelabs","g-suite","gcp","google-api","google-apps","google-cloud","google-cloud-platform","google-cloud-storage","google-cloud-vision","google-drive","google-sheets","gsuite","oauth2","storage"],"latest_commit_sha":null,"homepage":"http://g.co/codelabs/drive-gcs-vision-sheets","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/googlecodelabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-06T17:06:33.000Z","updated_at":"2024-05-09T07:22:08.000Z","dependencies_parsed_at":"2023-05-12T10:30:55.262Z","dependency_job_id":null,"html_url":"https://github.com/googlecodelabs/analyze_gsimg","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/googlecodelabs/analyze_gsimg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googlecodelabs%2Fanalyze_gsimg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googlecodelabs%2Fanalyze_gsimg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googlecodelabs%2Fanalyze_gsimg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googlecodelabs%2Fanalyze_gsimg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/googlecodelabs","download_url":"https://codeload.github.com/googlecodelabs/analyze_gsimg/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googlecodelabs%2Fanalyze_gsimg/sbom","scorecard":{"id":439868,"data":{"date":"2025-08-11","repo":{"name":"github.com/googlecodelabs/analyze_gsimg","commit":"96f0eb8aaefc15e8b65493dd85ff99496fb7f8c5"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/9 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-19T05:22:20.332Z","repository_id":149200452,"created_at":"2025-08-19T05:22:20.332Z","updated_at":"2025-08-19T05:22:20.332Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28914895,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-30T12:13:43.263Z","status":"ssl_error","status_checked_at":"2026-01-30T12:13:22.389Z","response_time":66,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","authorization","authorization-scheme","cloud-apis","cloud-storage","cloud-vision","codelabs","g-suite","gcp","google-api","google-apps","google-cloud","google-cloud-platform","google-cloud-storage","google-cloud-vision","google-drive","google-sheets","gsuite","oauth2","storage"],"created_at":"2024-08-05T06:01:47.561Z","updated_at":"2026-01-30T14:59:53.549Z","avatar_url":"https://github.com/googlecodelabs.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# Cloud image processing workflow:\n### Image archive, analysis, and report generation with Google Workspace (formerly G Suite) \u0026 GCP\n\nIn the [intermediate codelab tutorial](https://codelabs.developers.google.com/codelabs/drive-gcs-vision-sheets?utm_source=codelabs\u0026utm_medium=et\u0026utm_campaign=CDR_wes_workplace_gsdsanalyzegsimg_gsds_200114\u0026utm_content=-), developers build a cloud-based image processing workflow in Python along with Google Cloud REST APIs from [GCP](http://cloud.google.com) and [Google Workspace (formerly G Suite)](http://developers.google.com/gsuite). The exercise imagines an enterprise scenario where an organization can backup data (image files, for example) to the cloud, analyze them with machine learning, and report results formatted for consumption by management. This repo provides code solutions for each step through the tutorial plus alternate versions featuring other libraries and/or authorization schemes.\n\nThis is an intermediate codelab. If you're new to using Google APIs, specifically Google Workspace (formerly G Suite) and/or GCP APIs, we recommend completing the introductory codelabs (listed at the bottom of this page) first. You can read more about this code sample and codelab in [this Google Developers blog post](https://developers.googleblog.com/2020/10/image-archive-analysis-and-report?utm_source=ext\u0026utm_medium=partner\u0026utm_campaign=CDR_wes_workplace_gsdsanalyzegsimg_gsds_200114\u0026utm_content=-) or [this equivalent post on the Google Cloud blog](https://cloud.google.com/blog/topics/developers-practitioners/image-archive-analysis-and-report-generation-google-apis?utm_source=blog\u0026utm_medium=partner\u0026utm_campaign=CDR_wes_workplace_gsdsanalyzegsimg_gsds_200114).\n\n\n## Prerequisites\n\n- A Google account (Google Workspace/G Suite accounts may require administrator approval)\n- A Google Cloud Platform project with an active billing account\n- Familiarity with operating system terminal/shell commands\n- Basic skills in [Python](http://python.org) 2 or 3 ([other languages supported](http://developers.google.com/api-client-library))\n- Experience using Google APIs may be helpful but not required\n\n\u003e **NOTE for GCP developers**:\n\u003e The codelab does not use GCP [*product* client libraries](https://cloud.google.com/apis/docs/cloud-client-libraries) nor _service account_ authorization — instead it uses the lower-level *platform* client libraries (because non-Cloud APIs don't have product libraries yet) and _user account_ authorization (because the target file starts out in Google Drive). However, solutions featuring GCP product client libraries as well as service accounts are available as alternatives in the [`alt`](alt) folder.\n\n\n## Description\n\nThe primary objective is to **analyze Google Workspace images**... everything else (archiving, report generation) is a bonus. It starts with the image file on Google Drive, archives it to Google Cloud Storage, analyzes it with Cloud Vision, and writes a \"results\" row into a Google Sheet. Each step of the tutorial builds successively on the previous step, adding one feature at a time. Each of the `step*` directories represent the state the application should be in upon successful completion of that corresponding step in the codelab, culminating with a refactor step to arrive at the `final` version.\n\n1. **Download image from Google Drive**\n The first step utilizes the [Google Drive API](https://developers.google.com/drive) to search for the image file and downloads the first match. Along with the filename and binary payload, the file's MIMEtype, last modification timestamp, and size in bytes are also returned.\n\n1. **Backup image to Google Cloud Storage**\n The next step is to upload the image as a \"blob\" [object](https://cloud.google.com/storage/docs/key-terms#objects) to [Google Cloud Storage](https://cloud.google.com/storage) (GCS), performing an \"insert\" to the given [bucket](https://cloud.google.com/storage/docs/key-terms#buckets). Once data is in GCS, it can then be used by other GCP tools. GCS also supports cheaper, \"colder\" storage, meaning the less often you access objects, the lower the cost, as described on the [storage class page](https://cloud.google.com/storage/docs/storage-classes). NOTE: \"/\" in GCS filenames is merely a visual cue as GCS doesn't support \"folders.\" Our solution features an optional `PARENT` folder to help organize images in the destination bucket. (The GCP client libraries prep the data for GCS, so we need the *platform* client library [`MediaIoBaseUpload`](https://googleapis.github.io/google-api-python-client/docs/epy/googleapiclient.http.MediaIoBaseUpload-class.html) convenience object to help with the upload using the platform library.)\n\n1. **Send image to Cloud Vision for analysis**\n Since we have the image binary data, let's also send it to [Cloud Vision](https://cloud.google.com/vision) for analysis. Using its API, request object detection/identification (called [_label annotation_](https://cloud.google.com/vision/docs/labels)), but ask only for the top 5 labels for a faster response. Each label returned includes a confidence score the label applies to the image.\n\n1. **Add results to Google Sheets**\n The last new feature is report generation: add a spreadsheet row to visualize results via the [Google Sheets API](https://developers.google.com/sheets). The row includes the Cloud Vision output and the file's GCS archive hyperlinked location.\n\n1. \\***Refactor**\n The final, yet optional, step involves refactoring with best practices: move the \"main\" body into a separate function and supporting command-line options to provide user flexibility.\n\n\n## Authorization scheme and alternative versions\n\nWe've selected to use *user account authorization* (instead of *service account authorization*), *platform* client libraries (instead of *product* client libraries since those aren't available for Google Workspace (formerly G Suite) APIs), and older auth libraries for readability, consistency, greater Python 2-3 compatibility, and automated OAuth2 token management. This provides what we hope is the least complex user experience. Alternative versions (of the final application) using service accounts, product client libraries, and newer currently-supported auth libraries, are found in the [`alt`](alt) subdirectory. See its [README](alt/README.md) for more information.\n\n\n## Summary and further study\n\nThe goal of the codelab sample app is to help developers envision possible business scenarios. A secondary goal is showing how to use GCP and Google Workspace (formerly G Suite) APIs together for one solution. Problems with either the codelab or code in this repo? [File an issue](https://github.com/googlecodelabs/feedback/issues/new?title=[drive-gcs-vision-sheets]:\u0026labels[]=content-platform\u0026labels[]=cloud,python) (do a search first).\n\n\n# References\n\n- Codelabs\n    - [Intro to Workspace APIs (Google Drive API)](http://g.co/codelabs/gsuite-apis-intro) (Python)\n    - [Using Cloud Vision with Python](http://g.co/codelabs/vision-python) (Python)\n    - [Build customized reporting tools (Google Sheets API)](http://g.co/codelabs/sheets) (JS/Node)\n    - [Upload objects to Google Cloud Storage](http://codelabs.developers.google.com/codelabs/cloud-upload-objects-to-cloud-storage) (no coding required)\n- General\n    - [Google APIs client library for Python](https://developers.google.com/api-client-library/python)\n    - [Google APIs client libraries](https://developers.google.com/api-client-library)\n- Google Workspace\n    - [Google Drive API home page](https://developers.google.com/drive)\n    - [Google Sheets API home page](https://developers.google.com/sheets)\n    - [Google Workspace (formerly G Suite) developer overview \u0026 documentation](https://developers.google.com/gsuite).\n- Google Cloud Platform (GCP)\n    - [Google Cloud Storage home page](https://cloud.google.com/storage)\n    - [Google Cloud Vision home page \u0026 live demo](https://cloud.google.com/vision)\n        - [Cloud Vision API documentation](https://cloud.google.com/vision/docs)\n        - [Vision API image labeling docs](https://cloud.google.com/vision/docs/labels)\n    - [Python on the Google Cloud Platform](https://cloud.google.com/python)\n    - [GCP product client libraries](https://cloud.google.com/apis/docs/cloud-client-libraries)\n    - [GCP documentation](https://cloud.google.com/docs)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgooglecodelabs%2Fanalyze_gsimg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgooglecodelabs%2Fanalyze_gsimg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgooglecodelabs%2Fanalyze_gsimg/lists"}