Repository: GoogleCloudPlatform/automlops (language: python)

Issue:
Corrected spelling on names
Updated spelling of my last name.


Discussion / hints:

Fix patch:
diff --git a/AutoMLOps_User_Guide.pdf b/AutoMLOps_User_Guide.pdf
index 847541d..4c5ebad 100644
Binary files a/AutoMLOps_User_Guide.pdf and b/AutoMLOps_User_Guide.pdf differ
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a4e4a83..7809deb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,23 @@
 # Change Log
 All notable changes to this project will be documented in this file.
 
+## [1.2.3] - 2023-09-29
+
+### Added
+
+- Support for Github Actions integration
+- Added workload identity federation integration
+
+### Changed
+
+- Updated documentation
+- .git and relevant files are now placed inside the AutoMLOps/ base directory
+
+### Fixed
+
+- Set default cloud functions registry to the artifact-registry that is created as part of the provision operation
+
+
 ## [1.2.2] - 2023-09-25
 
 ### Added
diff --git a/README.md b/README.md
index dd3cfe6..4286e99 100644
--- a/README.md
+++ b/README.md
@@ -63,7 +63,7 @@ Inferencing
 
 **Deployment Frameworks**: Builds component docker containers, compiles pipelines, and submits Pipeline Jobs
 - Cloud Build
-- [coming soon] Github Actions
+- Github Actions
 - [coming soon] Gitlab CI
 - [coming soon] Bitbucket Pipelines
 - [coming soon] Jenkins
@@ -216,26 +216,30 @@ Optional parameters (defaults shown):
 12. `pipeline_job_submission_service_location: str = 'us-central1'`
 13. `pipeline_job_submission_service_name: str = f'{naming_prefix}-job-submission-svc'`
 14. `pipeline_job_submission_service_type: str = 'cloud-functions'`
-15. `provision_credentials_key: str = None`
-16. `provisioning_framework: str = 'gcloud'`
-17. `pubsub_topic_name: str = f'{naming_prefix}-queueing-svc'`
-18. `schedule_location: str = 'us-central1'`
-19. `schedule_name: str = f'{naming_prefix}-schedule'`
-20. `schedule_pattern: str = 'No Schedule Specified'`
-21. `source_repo_branch: str = 'automlops'`
-22. `source_repo_name: str = f'{naming_prefix}-repository'`
-23. `source_repo_type: str = 'cloud-source-repositories'`
-24. `storage_bucket_location: str = 'us-central1'`
-25. `storage_bucket_name: str = f'{project_id}-{naming_prefix}-bucket'`
-26. `use_ci: bool = False`
-27. `vpc_connector: str = 'No VPC Specified'`
+15. `project_number: str = None`
+16. `provision_credentials_key: str = None`
+17. `provisioning_framework: str = 'gcloud'`
+18. `pubsub_topic_name: str = f'{naming_prefix}-queueing-svc'`
+19. `schedule_location: str = 'us-central1'`
+20. `schedule_name: str = f'{naming_prefix}-schedule'`
+21. `schedule_pattern: str = 'No Schedule Specified'`
+22. `source_repo_branch: str = 'automlops'`
+23. `source_repo_name: str = f'{naming_prefix}-repository'`
+24. `source_repo_type: str = 'cloud-source-repositories'`
+25. `storage_bucket_location: str = 'us-central1'`
+26. `storage_bucket_name: str = f'{project_id}-{naming_prefix}-bucket'`
+27. `use_ci: bool = False`
+28. `vpc_connector: str = 'No VPC Specified'`
+29. `workload_identity_pool: str = None`
+30. `workload_identity_provider: str = None`
+31. `workload_identity_service_account: str = None`
 
 Parameter Options:
 - `artifact_repo_type=`:
     - 'artifact-registry' (default)
 - `deployment_framework=`:
     - 'cloud-build' (default)
-    - [coming soon] 'github-actions'
+    - 'github-actions'
     - [coming soon] 'gitlab-ci'
     - [coming soon] 'bitbucket-pipelines'
     - [coming soon] 'jenkins'
@@ -271,11 +275,12 @@ A description of the parameters is below:
 - `deployment_framework`: The CI tool to use (e.g. cloud build, github actions, etc.)
 - `naming_prefix`: Unique value used to differentiate pipelines and services across AutoMLOps runs.
 - `orchestration_framework`: The orchestration framework to use (e.g. kfp, tfx, etc.)
-- `pipeline_job_runner_service_account`: Service Account to run PipelineJobs.
+- `pipeline_job_runner_service_account`: Service Account to run PipelineJobs (specify the full string).
 - `pipeline_job_submission_service_location`: The location of the cloud submission service.
 - `pipeline_job_submission_service_name`: The name of the cloud submission service.
 - `pipeline_job_submission_service_type`: The tool to host for the cloud submission service (e.g. cloud run, cloud functions).
 - `precheck`: Boolean used to specify whether to check for provisioned resources before deploying.
+- `project_number`: The project number.
 - `provision_credentials_key`: Either a path to or the contents of a service account key file in JSON format.
 - `provisioning_framework`: The IaC tool to use (e.g. Terraform, Pulumi, etc.)
 - `pubsub_topic_name`: The name of the pubsub topic to publish to.
@@ -290,6 +295,9 @@ A description of the parameters is below:
 - `hide_warnings`: Boolean used to specify whether to show provision/deploy permission warnings
 - `use_ci`: Flag that determines whether to use Cloud CI/CD.
 - `vpc_connector`: The name of the vpc connector to use.
+- `workload_identity_pool`: Pool for workload identity federation. 
+- `workload_identity_provider`: Provider for workload identity federation.
+- `workload_identity_service_account`: Service account for workload identity federation (specify the full string).
 
 AutoMLOps will generate the resources specified by these parameters (e.g. Artifact Registry, Cloud Source Repo, etc.). If use_ci is set to True, AutoMLOps will turn the current working directory of the notebook into a Git repo and use it for the source repo. Additionally, if a cron formatted str is given as an arg for `schedule_pattern` then it will set up a Cloud Schedule to run accordingly.
 
@@ -333,7 +341,7 @@ AutoMLOps generates code that is compatible with `kfp<2.0.0`. Upon running `Auto
         ├── requirements.txt                       : Package requirements for the REST API service.
         ├── main.py                                : Python REST API source code.
 ├── README.md                                      : Readme markdown file describing the contents of the generated directories.
-└── cloudbuild.yaml                                : Cloudbuild configuration file for building custom components.
+└── Build config yaml                              : Build configuration file for building custom components.
 ```
 
 # Provisioning
@@ -370,6 +378,22 @@ If `use_ci=True`, AutoMLOps will generate and use a fully featured CI/CD environ
 
 # Other Customizations
 
+**Using Github Actions:**
+
+To use Github Actions integration, you must first have a [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation) set up properly. You must use a pre-existing Github repo, and you must also have already set up and registered your [ssh keys](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account) with your Github Repo. If you meet all of these prerequisites, you can use github actions as follows:
+```
+AutoMLOps.generate(project_id=PROJECT_ID,
+                   pipeline_params=pipeline_params,
+                   use_ci=True,
+                   deployment_framework='github-actions',
+                   project_number='<project_number>',
+                   source_repo_type='github',
+                   source_repo_name='source/repo/string',
+                   workload_identity_pool='identity_pool_string',
+                   workload_identity_provider='identity_provider_string',
+                   workload_identity_service_account='workload_identity_sa')
+```
+
 **Set scheduled run:**
 
 Use the `schedule_pattern` parameter to specify a cron job schedule to run the pipeline job on a recurring basis.
diff --git a/examples/training/.gcloudignore b/examples/training/.gcloudignore
deleted file mode 100644
index 5a616cb..0000000
--- a/examples/training/.gcloudignore
+++ /dev/null
@@ -1,17 +0,0 @@
-# This file specifies files that are *not* uploaded to Google Cloud
-# using gcloud. It follows the same syntax as .gitignore, with the addition of
-# "#!include" directives (which insert the entries of the given .gitignore-style
-# file at that point).
-#
-# For more information, run:
-#   $ gcloud topic gcloudignore
-#
-.gcloudignore
-# If you would like to upload your .git directory, .gitignore file or files
-# from your .gitignore file, remove the corresponding line
-# below:
-.git
-.gitignore
-
-node_modules
-#!include:.gitignore
diff --git a/examples/training/.gitignore b/examples/training/.gitignore
deleted file mode 100644
index 383728e..0000000
--- a/examples/training/.gitignore
+++ /dev/null
@@ -1,149 +0,0 @@
-.AutoMLOps-cache/
-.DS_Store
-.vscode
-
-# Terraform
-.terraform/
-
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-*$py.class
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-build/
-build/*
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-wheels/
-share/python-wheels/
-*.egg-info/
-.installed.cfg
-*.egg
-MANIFEST
-
-# PyInstaller
-#  Usually these files are written by a python script from a template
-#  before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.nox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*.cover
-*.py,cover
-.hypothesis/
-.pytest_cache/
-cover/
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-local_settings.py
-db.sqlite3
-db.sqlite3-journal
-
-# Flask stuff:
-instance/
-.webassets-cache
-
-# Scrapy stuff:
-.scrapy
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-.pybuilder/
-target/
-
-# Jupyter Notebook
-.ipynb_checkpoints
-
-# IPython
-profile_default/
-ipython_config.py
-
-# pyenv
-#   For a library or package, you might want to ignore these files since the code is
-#   intended to run in multiple environments; otherwise, check them in:
-# .python-version
-
-# pipenv
-#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
-#   However, in case of collaboration, if having platform-specific dependencies or dependencies
-#   having no cross-platform support, pipenv may install dependencies that don't work, or not
-#   install all needed dependencies.
-#Pipfile.lock
-
-# PEP 582; used by e.g. github.com/David-OConnor/pyflow
-__pypackages__/
-
-# Celery stuff
-celerybeat-schedule
-celerybeat.pid
-
-# SageMath parsed files
-*.sage.py
-
-# Environments
-.env
-.venv
-env/
-venv/
-ENV/
-env.bak/
-venv.bak/
-
-# Spyder project settings
-.spyderproject
-.spyproject
-
-# Rope project settings
-.ropeproject
-
-# mkdocs documentation
-/site
-
-# mypy
-.mypy_cache/
-.dmypy.json
-dmypy.json
-
-# Pyre type checker
-.pyre/
-
-# pytype static type analyzer
-.pytype/
-
-# Cython debug symbols
-cython_debug/
-
-# Local Configs
-config.yaml
\ No newline at end of file
diff --git a/examples/training/00_introduction_training_example.ipynb b/examples/training/00_introduction_training_example.ipynb
index 6b648ff..b5cd256 100644
--- a/examples/training/00_introduction_training_example.ipynb
+++ b/examples/training/00_introduction_training_example.ipynb
@@ -472,7 +472,7 @@
     "    \"\"\"Custom component that trains a decision tree on the training data.\n",
     "\n",
     "    Args:\n",
-    "        data_path: GS location where the training data.\n",
+    "        data_path: GS location of the training data.\n",
     "        model_directory: GS location of saved model.\n",
     "    \"\"\"\n",
     "    from sklearn.tree import DecisionTreeClassifier\n",
@@ -697,49 +697,49 @@
      "output_type": "stream",
      "text": [
       "WARNING: Provisioning requires these permissions:\n",
-      "-iam.serviceAccounts.create\n",
+      "-cloudbuild.builds.create\n",
+      "-pubsub.topics.list\n",
       "-serviceusage.services.enable\n",
-      "-cloudfunctions.functions.create\n",
-      "-iam.serviceAccounts.list\n",
-      "-source.repos.list\n",
-      "-pubsub.topics.create\n",
-      "-storage.buckets.create\n",
-      "-source.repos.create\n",
+      "-storage.buckets.get\n",
+      "-iam.serviceAccounts.actAs\n",
       "-cloudscheduler.jobs.create\n",
-      "-resourcemanager.projects.setIamPolicy\n",
       "-pubsub.subscriptions.list\n",
-      "-serviceusage.services.use\n",
-      "-storage.buckets.get\n",
-      "-cloudbuild.builds.create\n",
-      "-pubsub.subscriptions.create\n",
-      "-artifactregistry.repositories.list\n",
+      "-pubsub.topics.create\n",
       "-cloudfunctions.functions.get\n",
-      "-cloudbuild.builds.list\n",
       "-artifactregistry.repositories.create\n",
       "-cloudscheduler.jobs.list\n",
-      "-iam.serviceAccounts.actAs\n",
-      "-pubsub.topics.list\n",
+      "-pubsub.subscriptions.create\n",
+      "-iam.serviceAccounts.create\n",
+      "-resourcemanager.projects.setIamPolicy\n",
+      "-iam.serviceAccounts.list\n",
+      "-cloudfunctions.functions.create\n",
+      "-source.repos.list\n",
+      "-source.repos.create\n",
+      "-artifactregistry.repositories.list\n",
+      "-storage.buckets.create\n",
+      "-serviceusage.services.use\n",
+      "-cloudbuild.builds.list\n",
       "\n",
       "You are currently using: srastatter@google.com. Please check your account permissions.\n",
       "The following are the recommended roles for provisioning:\n",
-      "-roles/serviceusage.serviceUsageAdmin\n",
-      "-roles/artifactregistry.admin\n",
       "-roles/cloudbuild.builds.editor\n",
       "-roles/resourcemanager.projectIamAdmin\n",
-      "-roles/cloudscheduler.admin\n",
-      "-roles/iam.serviceAccountUser\n",
-      "-roles/iam.serviceAccountAdmin\n",
-      "-roles/storage.admin\n",
-      "-roles/cloudfunctions.admin\n",
       "-roles/pubsub.editor\n",
       "-roles/source.admin\n",
+      "-roles/iam.serviceAccountUser\n",
+      "-roles/serviceusage.serviceUsageAdmin\n",
+      "-roles/cloudfunctions.admin\n",
+      "-roles/storage.admin\n",
+      "-roles/artifactregistry.admin\n",
+      "-roles/cloudscheduler.admin\n",
+      "-roles/iam.serviceAccountAdmin\n",
       "\n",
       "\u001b[0;32m Setting up API services in project automlops-sandbox \u001b[0m\n",
-      "Operation \"operations/acat.p2-45373616427-774ab104-8889-497b-a35a-5dea7ab8bb32\" finished successfully.\n",
+      "Operation \"operations/acat.p2-45373616427-64a80155-46ca-4ebb-abc4-66904d81e9ea\" finished successfully.\n",
       "\u001b[0;32m Setting up Artifact Registry in project automlops-sandbox \u001b[0m\n",
       "Listing items under project automlops-sandbox, location us-central1.\n",
       "\n",
-      "dry-beans-dt-artifact-registry    DOCKER  STANDARD_REPOSITORY  Artifact Registry dry-beans-dt-artifact-registry in us-central1.                            us-central1                                  Google-managed key  2023-09-05T11:25:48  2023-09-20T14:07:57  9794.524\n",
+      "dry-beans-dt-artifact-registry    DOCKER  STANDARD_REPOSITORY  Artifact Registry dry-beans-dt-artifact-registry in us-central1.                            us-central1                                  Google-managed key  2023-09-05T11:25:48  2023-09-28T23:31:56  11640.147\n",
       "Artifact Registry: dry-beans-dt-artifact-registry already exists in project automlops-sandbox\n",
       "\u001b[0;32m Setting up Storage Bucket in project automlops-sandbox \u001b[0m\n",
       "gs://automlops-sandbox-dry-beans-dt-bucket/\n",
@@ -749,7 +749,7 @@
       "Service Account: vertex-pipelines already exists in project automlops-sandbox\n",
       "\u001b[0;32m Setting up IAM roles for Pipeline Job Runner Service Account in project automlops-sandbox \u001b[0m\n",
       "\u001b[0;32m Setting up Cloud Source Repository in project automlops-sandbox \u001b[0m\n",
-      "dry-beans-dt-repository    automlops-sandbox  https://source.developers.google.com/p/automlops-sandbox/r/dry-beans-dt-repository\n",
+      "dry-beans-dt-repository  automlops-sandbox  https://source.developers.google.com/p/automlops-sandbox/r/dry-beans-dt-repository\n",
       "Cloud Source Repository: dry-beans-dt-repository already exists in project automlops-sandbox\n",
       "\u001b[0;32m Setting up Queueing Service in project automlops-sandbox \u001b[0m\n",
       "name: projects/automlops-sandbox/topics/dry-beans-dt-queueing-svc\n",
@@ -757,12 +757,13 @@
       "\u001b[0;32m Deploying Cloud Functions: dry-beans-dt-job-submission-svc in project automlops-sandbox \u001b[0m\n",
       "Deploying function (may take a while - up to 2 minutes)...\n",
       "..\n",
-      "For Cloud Build Logs, visit: https://console.cloud.google.com/cloud-build/builds;region=us-central1/09aeff6a-d087-44fc-a700-c854f10388b2?project=45373616427\n",
-      "...............................................................done.\n",
+      "For Cloud Build Logs, visit: https://console.cloud.google.com/cloud-build/builds;region=us-central1/2023b741-7039-4edc-8e70-61da23715920?project=45373616427\n",
+      ".............................done.\n",
       "availableMemoryMb: 512\n",
-      "buildId: 09aeff6a-d087-44fc-a700-c854f10388b2\n",
-      "buildName: projects/45373616427/locations/us-central1/builds/09aeff6a-d087-44fc-a700-c854f10388b2\n",
+      "buildId: 2023b741-7039-4edc-8e70-61da23715920\n",
+      "buildName: projects/45373616427/locations/us-central1/builds/2023b741-7039-4edc-8e70-61da23715920\n",
       "dockerRegistry: ARTIFACT_REGISTRY\n",
+      "dockerRepository: projects/automlops-sandbox/locations/us-central1/repositories/dry-beans-dt-artifact-registry\n",
       "entryPoint: process_request\n",
       "eventTrigger:\n",
       "  eventType: google.pubsub.topic.publish\n",
@@ -776,16 +777,16 @@
       "name: projects/automlops-sandbox/locations/us-central1/functions/dry-beans-dt-job-submission-svc\n",
       "runtime: python39\n",
       "serviceAccountEmail: vertex-pipelines@automlops-sandbox.iam.gserviceaccount.com\n",
-      "sourceUploadUrl: https://storage.googleapis.com/uploads-961973632599.us-central1.cloudfunctions.appspot.com/fc8a1e99-593a-4b71-b489-46db398c8194.zip\n",
+      "sourceUploadUrl: https://storage.googleapis.com/uploads-961973632599.us-central1.cloudfunctions.appspot.com/7e2fe33a-4a5b-4103-8a9c-e81855325ba4.zip\n",
       "status: ACTIVE\n",
       "timeout: 540s\n",
-      "updateTime: '2023-09-25T17:12:41.289Z'\n",
-      "versionId: '6'\n",
+      "updateTime: '2023-09-29T03:41:11.731Z'\n",
+      "versionId: '2'\n",
       "\u001b[0;32m Setting up Cloud Build Trigger in project automlops-sandbox \u001b[0m\n",
       "name: dry-beans-dt-build-trigger\n",
       "Cloudbuild Trigger already exists in project automlops-sandbox for repo dry-beans-dt-repository\n",
       "\u001b[0;32m Setting up Cloud Scheduler Job in project automlops-sandbox \u001b[0m\n",
-      "dry-beans-dt-schedule    us-central1  59 11 * * 0 (Etc/UTC)  Pub/Sub      ENABLED\n",
+      "dry-beans-dt-schedule  us-central1  59 11 * * 0 (Etc/UTC)  Pub/Sub      ENABLED\n",
       "Cloud Scheduler Job: dry-beans-dt-schedule already exists in project automlops-sandbox\n"
      ]
     }
@@ -815,28 +816,28 @@
      "output_type": "stream",
      "text": [
       "WARNING: Running precheck for deploying requires these permissions:\n",
-      "-cloudbuild.builds.get\n",
-      "-storage.buckets.update\n",
-      "-cloudfunctions.functions.get\n",
       "-artifactregistry.repositories.get\n",
       "-iam.serviceAccounts.get\n",
-      "-pubsub.topics.get\n",
-      "-serviceusage.services.get\n",
       "-source.repos.update\n",
-      "-pubsub.subscriptions.get\n",
       "-resourcemanager.projects.getIamPolicy\n",
+      "-serviceusage.services.get\n",
+      "-pubsub.topics.get\n",
+      "-cloudbuild.builds.get\n",
+      "-cloudfunctions.functions.get\n",
+      "-storage.buckets.update\n",
+      "-pubsub.subscriptions.get\n",
       "\n",
       "You are currently using: srastatter@google.com. Please check your account permissions.\n",
       "The following are the recommended roles for deploying with precheck:\n",
       "-roles/serviceusage.serviceUsageViewer\n",
       "-roles/cloudbuild.builds.editor\n",
-      "-roles/source.writer\n",
       "-roles/iam.serviceAccountUser\n",
-      "-roles/iam.roleViewer\n",
       "-roles/pubsub.viewer\n",
-      "-roles/storage.admin\n",
       "-roles/cloudfunctions.viewer\n",
+      "-roles/storage.admin\n",
       "-roles/artifactregistry.reader\n",
+      "-roles/source.writer\n",
+      "-roles/iam.roleViewer\n",
       "\n",
       "Checking for required API services in project automlops-sandbox...\n",
       "Checking for Artifact Registry in project automlops-sandbox...\n",
@@ -850,11 +851,11 @@
       "Checking for Cloud Build Trigger in project automlops-sandbox...\n",
       "Precheck successfully completed, continuing to deployment.\n",
       "\n",
-      "[automlops 21e4739] Run AutoMLOps\n",
-      " 2 files changed, 14 insertions(+), 16 deletions(-)\n",
-      "remote: Waiting for private key checker: 2/2 objects left        \n",
+      "[automlops d425a62] Run AutoMLOps\n",
+      " 3 files changed, 18 insertions(+), 18 deletions(-)\n",
+      "remote: Waiting for private key checker: 3/3 objects left        \n",
       "To https://source.developers.google.com/p/automlops-sandbox/r/dry-beans-dt-repository\n",
-      "   4c3cee5..21e4739  automlops -> automlops\n",
+      "   33e4088..d425a62  automlops -> automlops\n",
       "Pushing code to automlops branch, triggering build...\n",
       "Cloud Build job running at: https://console.cloud.google.com/cloud-build/builds;region=us-central1\n",
       "Please wait for this build job to complete.\n",
@@ -899,10 +900,26 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 12,
    "id": "89f42645",
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Writing directories under AutoMLOps/\n",
+      "Writing configurations to AutoMLOps/configs/defaults.yaml\n",
+      "Writing README.md to AutoMLOps/README.md\n",
+      "Writing kubeflow pipelines code to AutoMLOps/pipelines, AutoMLOps/components\n",
+      "Writing scripts to AutoMLOps/scripts\n",
+      "Writing submission service code to AutoMLOps/services\n",
+      "Writing gcloud provisioning code to AutoMLOps/provision\n",
+      "Writing cloud build config to AutoMLOps/cloudbuild.yaml\n",
+      "Code Generation Complete.\n"
+     ]
+    }
+   ],
    "source": [
     "AutoMLOps.generate(project_id=PROJECT_ID, \n",
     "                   pipeline_params=pipeline_params, \n",
@@ -943,11 +960,12 @@
     "- `deployment_framework`: The CI tool to use (e.g. cloud build, github actions, etc.)\n",
     "- `naming_prefix`: Unique value used to differentiate pipelines and services across AutoMLOps runs.\n",
     "- `orchestration_framework`: The orchestration framework to use (e.g. kfp, tfx, etc.)\n",
-    "- `pipeline_job_runner_service_account`: Service Account to run PipelineJobs.\n",
+    "- `pipeline_job_runner_service_account`: Service Account to run PipelineJobs (specify the full string).\n",
     "- `pipeline_job_submission_service_location`: The location of the cloud submission service.\n",
     "- `pipeline_job_submission_service_name`: The name of the cloud submission service.\n",
     "- `pipeline_job_submission_service_type`: The tool to host for the cloud submission service (e.g. cloud run, cloud functions).\n",
     "- `precheck`: Boolean used to specify whether to check for provisioned resources before deploying.\n",
+    "- `project_number`: The project number.\n",
     "- `provision_credentials_key`: Either a path to or the contents of a service account key file in JSON format.\n",
     "- `provisioning_framework`: The IaC tool to use (e.g. Terraform, Pulumi, etc.)\n",
     "- `pubsub_topic_name`: The name of the pubsub topic to publish to.\n",
@@ -962,6 +980,9 @@
     "- `hide_warnings`: Boolean used to specify whether to show provision/deploy permission warnings\n",
     "- `use_ci`: Flag that determines whether to use Cloud CI/CD.\n",
     "- `vpc_connector`: The name of the vpc connector to use.\n",
+    "- `workload_identity_pool`: Pool for workload identity federation. \n",
+    "- `workload_identity_provider`: Provider for workload identity federation.\n",
+    "- `workload_identity_service_account`: Service account for workload identity federation (specify the full string).\n",
     "\n",
     "The `use_ci` parameter specifies whether to use the generated `scripts/run_all.sh` local script to submit the build job and PipelineJob. If this parameter is set to False, `AutoMLOps` will use the cloud [CI/CD workflow](https://github.com/GoogleCloudPlatform/automlops#deployment). The run above uses `use_ci=True`, and the run below uses `use_ci=False`, notice the differences in output (`use_ci=False` means you will not use the Source Repository to trigger build jobs on push). "
    ]
@@ -1005,6 +1026,7 @@
     "                   pipeline_job_submission_service_location='us-central1', # default\n",
     "                   pipeline_job_submission_service_name=None, # default\n",
     "                   pipeline_job_submission_service_type='cloud-functions', # default\n",
+    "                   project_number=None, # default\n",
     "                   provision_credentials_key=None, # default\n",
     "                   provisioning_framework='gcloud', # default\n",
     "                   pubsub_topic_name=None, # default\n",
@@ -1018,6 +1040,9 @@
     "                   storage_bucket_name=None, # default\n",
     "                   use_ci=False, # default\n",
     "                   vpc_connector='No VPC Specified', # default\n",
+    "                   workload_identity_pool=None, # default\n",
+    "                   workload_identity_provider=None, # default\n",
+    "                   workload_identity_service_account=None, # default\n",
     ")"
    ]
   },
diff --git a/google_cloud_automlops/AutoMLOps.py b/google_cloud_automlops/AutoMLOps.py
index 06512ff..69d6d10 100644
--- a/google_cloud_automlops/AutoMLOps.py
+++ b/google_cloud_automlops/AutoMLOps.py
@@ -35,6 +35,7 @@
     DEFAULT_SOURCE_REPO_BRANCH,
     DEFAULT_VPC_CONNECTOR,
     GENERATED_CLOUDBUILD_FILE,
+    GENERATED_GITHUB_ACTIONS_FILE,
     GENERATED_DEFAULTS_FILE,
     GENERATED_DIRS,
     GENERATED_RESOURCES_SH_FILE,
@@ -77,13 +78,15 @@
 )
 # Deployment imports
 from google_cloud_automlops.deployments.cloudbuild import builder as CloudBuildBuilder
+from google_cloud_automlops.deployments.github_actions import builder as GithubActionsBuilder
 from google_cloud_automlops.deployments.enums import (
     ArtifactRepository,
     CodeRepository,
     Deployer
 )
 from google_cloud_automlops.deployments.configs import (
-    CloudBuildConfig
+    CloudBuildConfig,
+    GitHubActionsConfig
 )
 from google_cloud_automlops.deployments.gitops.git_utils import git_workflow
 
@@ -112,6 +115,7 @@ def launchAll(
     pipeline_job_submission_service_name: Optional[str] = None,
     pipeline_job_submission_service_type: Optional[str] = PipelineJobSubmitter.CLOUD_FUNCTIONS.value,
     precheck: Optional[bool] = True,
+    project_number: Optional[str] = None,
     provision_credentials_key: str = None,
     provisioning_framework: Optional[str] = Provisioner.GCLOUD.value,
     pubsub_topic_name: Optional[str] = None,
@@ -125,7 +129,10 @@ def launchAll(
     storage_bucket_name: Optional[str] = None,
     hide_warnings: Optional[bool] = True,
     use_ci: Optional[bool] = False,
-    vpc_connector: Optional[str] = DEFAULT_VPC_CONNECTOR):
+    vpc_connector: Optional[str] = DEFAULT_VPC_CONNECTOR,
+    workload_identity_pool: Optional[str] = None,
+    workload_identity_provider: Optional[str] = None,
+    workload_identity_service_account: Optional[str] = None):
     """Generates relevant pipeline and component artifacts,
        then provisions resources, builds, compiles, and submits the PipelineJob.
        Check constants file for variable default values.
@@ -143,11 +150,12 @@ def launchAll(
         deployment_framework: The CI tool to use (e.g. cloud build, github actions, etc.)
         naming_prefix: Unique value used to differentiate pipelines and services across AutoMLOps runs.
         orchestration_framework: The orchestration framework to use (e.g. kfp, tfx, etc.)
-        pipeline_job_runner_service_account: Service Account to run PipelineJobs.
+        pipeline_job_runner_service_account: Service Account to run PipelineJobs (specify the full string).
         pipeline_job_submission_service_location: The location of the cloud submission service.
         pipeline_job_submission_service_name: The name of the cloud submission service.
         pipeline_job_submission_service_type: The tool to host for the cloud submission service (e.g. cloud run, cloud functions).
         precheck: Boolean used to specify whether to check for provisioned resources before deploying.
+        project_number: The project number.
         provision_credentials_key: Either a path to or the contents of a service account key file in JSON format.
         provisioning_framework: The IaC tool to use (e.g. Terraform, Pulumi, etc.)
         pubsub_topic_name: The name of the pubsub topic to publish to.
@@ -162,6 +170,9 @@ def launchAll(
         hide_warnings: Boolean used to specify whether to show provision/deploy permission warnings
         use_ci: Flag that determines whether to use Cloud CI/CD.
         vpc_connector: The name of the vpc connector to use.
+        workload_identity_pool: Pool for workload identity federation. 
+        workload_identity_provider: Provider for workload identity federation.
+        workload_identity_service_account: Service account for workload identity federation (specify the full string).
     """
     generate(
         project_id=project_id,
@@ -180,6 +191,7 @@ def launchAll(
         pipeline_job_submission_service_location=pipeline_job_submission_service_location,
         pipeline_job_submission_service_name=pipeline_job_submission_service_name,
         pipeline_job_submission_service_type=pipeline_job_submission_service_type,
+        project_number=project_number,
         provisioning_framework=provisioning_framework,
         provision_credentials_key=provision_credentials_key,
         pubsub_topic_name=pubsub_topic_name,
@@ -192,7 +204,10 @@ def launchAll(
         storage_bucket_location=storage_bucket_location,
         storage_bucket_name=storage_bucket_name,
         use_ci=use_ci,
-        vpc_connector=vpc_connector)
+        vpc_connector=vpc_connector,
+        workload_identity_pool=workload_identity_pool,
+        workload_identity_provider=workload_identity_provider,
+        workload_identity_service_account=workload_identity_service_account)
     provision(hide_warnings=hide_warnings)
     deploy(hide_warnings=hide_warnings, precheck=precheck)
 
@@ -214,6 +229,7 @@ def generate(
     pipeline_job_submission_service_location: Optional[str] = DEFAULT_RESOURCE_LOCATION,
     pipeline_job_submission_service_name: Optional[str] = None,
     pipeline_job_submission_service_type: Optional[str] = PipelineJobSubmitter.CLOUD_FUNCTIONS.value,
+    project_number: Optional[str] = None,
     provision_credentials_key: str = None,
     provisioning_framework: Optional[str] = Provisioner.GCLOUD.value,
     pubsub_topic_name: Optional[str] = None,
@@ -226,7 +242,10 @@ def generate(
     storage_bucket_location: Optional[str] = DEFAULT_RESOURCE_LOCATION,
     storage_bucket_name: Optional[str] = None,
     use_ci: Optional[bool] = False,
-    vpc_connector: Optional[str] = DEFAULT_VPC_CONNECTOR):
+    vpc_connector: Optional[str] = DEFAULT_VPC_CONNECTOR,
+    workload_identity_pool: Optional[str] = None, #TODO: integrate optional creation of pool and provider during provisioning stage
+    workload_identity_provider: Optional[str] = None,
+    workload_identity_service_account: Optional[str] = None):
     """Generates relevant pipeline and component artifacts.
        Check constants file for variable default values.
 
@@ -381,6 +400,21 @@ def generate(
                 project_id=project_id,
                 pubsub_topic_name=derived_pubsub_topic_name,
                 use_ci=use_ci))
+    if deployment_framework == Deployer.GITHUB_ACTIONS.value:
+        if project_number is None:
+            raise ValueError('Project number must be specified in order to use to use Github Actions integration.')
+        logging.info(f'Writing GitHub Actions config to {GENERATED_GITHUB_ACTIONS_FILE}')
+        GithubActionsBuilder.build(GitHubActionsConfig(
+                artifact_repo_location=artifact_repo_location,
+                artifact_repo_name=derived_artifact_repo_name,
+                naming_prefix=naming_prefix,
+                project_id=project_id,
+                project_number=project_number,
+                pubsub_topic_name=derived_pubsub_topic_name,
+                use_ci=use_ci,
+                workload_identity_pool=workload_identity_pool,
+                workload_identity_provider=workload_identity_provider,
+                workload_identity_service_account=workload_identity_service_account))
     logging.info('Code Generation Complete.')
 
 
diff --git a/google_cloud_automlops/__init__.py b/google_cloud_automlops/__init__.py
index 8f99b04..546f3fa 100644
--- a/google_cloud_automlops/__init__.py
+++ b/google_cloud_automlops/__init__.py
@@ -23,6 +23,6 @@
 series of directories to support the creation of Vertex Pipelines.
 """
 # pylint: disable=invalid-name
-__version__ = '1.2.2'
+__version__ = '1.2.3'
 __author__ = 'Sean Rastatter'
 __credits__ = 'Google'
diff --git a/google_cloud_automlops/deployments/cloudbuild/builder.py b/google_cloud_automlops/deployments/cloudbuild/builder.py
index f392a86..60fda26 100644
--- a/google_cloud_automlops/deployments/cloudbuild/builder.py
+++ b/google_cloud_automlops/deployments/cloudbuild/builder.py
@@ -26,10 +26,9 @@
 
 from google_cloud_automlops.utils.utils import write_file
 from google_cloud_automlops.utils.constants import (
-    BASE_DIR,
     CLOUDBUILD_TEMPLATES_PATH,
     GENERATED_CLOUDBUILD_FILE,
-    GENERATED_COMPONENT_BASE,
+    COMPONENT_BASE_RELATIVE_PATH,
     GENERATED_LICENSE,
     GENERATED_PARAMETER_VALUES_PATH
 )
@@ -83,8 +82,7 @@ def create_cloudbuild_jinja(
         return template.render(
             artifact_repo_location=artifact_repo_location,
             artifact_repo_name=artifact_repo_name,
-            base_dir=BASE_DIR,
-            generated_component_base=GENERATED_COMPONENT_BASE,
+            component_base_relative_path=COMPONENT_BASE_RELATIVE_PATH,
             generated_license=GENERATED_LICENSE,
             generated_parameter_values_path=GENERATED_PARAMETER_VALUES_PATH,
             naming_prefix=naming_prefix,
diff --git a/google_cloud_automlops/deployments/cloudbuild/templates/cloudbuild.yaml.j2 b/google_cloud_automlops/deployments/cloudbuild/templates/cloudbuild.yaml.j2
index 59c6547..617574b 100644
--- a/google_cloud_automlops/deployments/cloudbuild/templates/cloudbuild.yaml.j2
+++ b/google_cloud_automlops/deployments/cloudbuild/templates/cloudbuild.yaml.j2
@@ -8,7 +8,7 @@ steps:
   - name: "gcr.io/cloud-builders/docker"
     args: [ "build", "-t", "{{artifact_repo_location}}-docker.pkg.dev/{{project_id}}/{{artifact_repo_name}}/{{naming_prefix}}/components/component_base:latest",
             "--cache-from", "{{artifact_repo_location}}-docker.pkg.dev/{{project_id}}/{{artifact_repo_name}}/{{naming_prefix}}/components/component_base:latest", "." ]
-    dir: "{{generated_component_base}}"
+    dir: "{{component_base_relative_path}}"
     id: "build_component_base"
     waitFor: ["-"]
 {% if use_ci %}
@@ -19,7 +19,7 @@ steps:
   # push the component_base image
   - name: "gcr.io/cloud-builders/docker"
     args: ["push", "{{artifact_repo_location}}-docker.pkg.dev/{{project_id}}/{{artifact_repo_name}}/{{naming_prefix}}/components/component_base:latest"]
-    dir: "{{generated_component_base}}"
+    dir: "{{component_base_relative_path}}"
     id: "push_component_base"
     waitFor: ["build_component_base"]
 
@@ -27,7 +27,6 @@ steps:
   - name: python
     entrypoint: pip
     args: ["install", "-r", "pipelines/requirements.txt", "--user"]
-    dir: "{{base_dir}}"
     id: "install_pipelines_deps"
     waitFor: ["push_component_base"]
 
@@ -35,7 +34,6 @@ steps:
   - name: python
     entrypoint: python
     args: ["-m", "pipelines.pipeline", "--config", "configs/defaults.yaml"]
-    dir: "{{base_dir}}"
     id: "build_pipeline_spec"
     waitFor: ["install_pipelines_deps"]
 
@@ -47,7 +45,6 @@ steps:
       - |
           gcloud pubsub topics publish {{pubsub_topic_name}} --message \
           "$(cat {{generated_parameter_values_path}})"
-    dir: "{{base_dir}}"
     id: "publish_to_topic"
     waitFor: ["build_pipeline_spec"]
 {% endif %}
diff --git a/google_cloud_automlops/deployments/configs.py b/google_cloud_automlops/deployments/configs.py
index 638566e..e907eb4 100644
--- a/google_cloud_automlops/deployments/configs.py
+++ b/google_cloud_automlops/deployments/configs.py
@@ -37,3 +37,30 @@ class CloudBuildConfig(BaseModel):
     project_id: str
     pubsub_topic_name: str
     use_ci: bool
+
+class GitHubActionsConfig(BaseModel):
+    """Model representing the GitHub Actions config.
+
+    Args:
+        artifact_repo_location: Region of the artifact repo (default use with Artifact Registry).
+        artifact_repo_name: Artifact repo name where components are stored (default use with Artifact Registry).
+        naming_prefix: Unique value used to differentiate pipelines and services across AutoMLOps runs.
+        project_id: The project ID.
+        project_number: The project number.
+        pubsub_topic_name: The name of the pubsub topic to publish to.
+        use_ci: Flag that determines whether to use Cloud CI/CD.
+        workload_identity_pool: Pool for workload identity federation. 
+        workload_identity_provider: Provider for workload identity federation.
+        workload_identity_service_account: Service account for workload identity federation. 
+    """
+    artifact_repo_location: str
+    artifact_repo_name: str
+    naming_prefix: str
+    project_id: str
+    project_number: str #TODO: Check if there's any other way to pass this, could use a util with the GCP client library. See https://github.com/GoogleCloudPlatform/java-docs-samples/blob/main/content-warehouse/src/main/java/contentwarehouse/v1/CreateDocument.java#L125-L135
+    pubsub_topic_name: str
+    use_ci: bool
+    workload_identity_pool: str
+    workload_identity_provider: str
+    workload_identity_service_account: str
+    
\ No newline at end of file
diff --git a/google_cloud_automlops/deployments/enums.py b/google_cloud_automlops/deployments/enums.py
index 133bafa..6ee768a 100644
--- a/google_cloud_automlops/deployments/enums.py
+++ b/google_cloud_automlops/deployments/enums.py
@@ -24,7 +24,7 @@ class Deployer(Enum):
     """Enum representing the available options for orchestration management."""
 
     CLOUDBUILD = 'cloud-build'
-    # GITHUB_ACTIONS = 'github-actions'   # roadmap item
+    GITHUB_ACTIONS = 'github-actions'
     # GITLAB_CI = 'gitlab-ci'   # roadmap item
     # JENKINS = 'jenkins'   # roadmap item
 
@@ -34,7 +34,7 @@ class CodeRepository(Enum):
 
     BITBUCKET = 'bitbucket'   # roadmap item
     CLOUD_SOURCE_REPOSITORIES = 'cloud-source-repositories'
-    GITHUB = 'github'   # roadmap item
+    GITHUB = 'github'
     GITLAB = 'gitlab'   # roadmap item
 
 
diff --git a/google_cloud_automlops/deployments/github_actions/.gitkeep b/google_cloud_automlops/deployments/github_actions/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/google_cloud_automlops/deployments/github_actions/__init__.py b/google_cloud_automlops/deployments/github_actions/__init__.py
new file mode 100644
index 0000000..2379f87
--- /dev/null
+++ b/google_cloud_automlops/deployments/github_actions/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2023 Google LLC. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/google_cloud_automlops/deployments/github_actions/builder.py b/google_cloud_automlops/deployments/github_actions/builder.py
new file mode 100644
index 0000000..2bcd020
--- /dev/null
+++ b/google_cloud_automlops/deployments/github_actions/builder.py
@@ -0,0 +1,113 @@
+# Copyright 2023 Google LLC. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Builds KFP components and pipeline."""
+
+# pylint: disable=line-too-long
+
+try:
+    from importlib.resources import files as import_files
+except ImportError:
+    # Try backported to PY<37 `importlib_resources`
+    from importlib_resources import files as import_files
+
+from jinja2 import Template
+
+from google_cloud_automlops.utils.utils import write_file
+from google_cloud_automlops.utils.constants import (
+    DEFAULT_SOURCE_REPO_BRANCH,
+    GENERATED_GITHUB_ACTIONS_FILE,
+    COMPONENT_BASE_RELATIVE_PATH,
+    GENERATED_LICENSE,
+    GENERATED_PARAMETER_VALUES_PATH,
+    GITHUB_ACTIONS_TEMPLATES_PATH
+)
+
+from google_cloud_automlops.deployments.configs import GitHubActionsConfig
+
+def build(config: GitHubActionsConfig):
+    """Constructs scripts for resource deployment and running Kubeflow pipelines.
+
+    Args:
+        config.artifact_repo_location: Region of the artifact repo (default use with Artifact Registry).
+        config.artifact_repo_name: Artifact repo name where components are stored (default use with Artifact Registry).
+        config.naming_prefix: Unique value used to differentiate pipelines and services across AutoMLOps runs.
+        config.project_id: The project ID.
+        config.project_number: The project number.
+        config.pubsub_topic_name: The name of the pubsub topic to publish to.
+        config.use_ci: Flag that determines whether to use Cloud CI/CD.
+        config.workload_identity_pool: Pool for workload identity federation. 
+        config.workload_identity_provider: Provider for workload identity federation.
+        config.workload_identity_service_account: Service account for workload identity federation. 
+    """
+    # Write github actions config
+    write_file(GENERATED_GITHUB_ACTIONS_FILE, create_github_actions_jinja(
+        config.artifact_repo_location,
+        config.artifact_repo_name,
+        config.naming_prefix,
+        config.project_id,
+        config.project_number,
+        config.pubsub_topic_name,
+        config.use_ci,
+        config.workload_identity_pool,
+        config.workload_identity_provider,
+        config.workload_identity_service_account), 'w')
+
+def create_github_actions_jinja(
+        artifact_repo_location: str,
+        artifact_repo_name: str,
+        naming_prefix: str,
+        project_id: str,
+        project_number: str,
+        pubsub_topic_name: str,
+        use_ci: bool,
+        workload_identity_pool: str,
+        workload_identity_provider: str,
+        workload_identity_service_account: str) -> str:
+    """Generates content for the github_actions.yaml, to be written to the .github/workflows directory.
+        This file contains the ci/cd manifest for AutoMLOps.
+
+    Args:
+        artifact_repo_location: Region of the artifact repo (default use with Artifact Registry).
+        artifact_repo_name: Artifact repo name where components are stored (default use with Artifact Registry).
+        naming_prefix: Unique value used to differentiate pipelines and services across AutoMLOps runs.
+        project_id: The project ID.
+        project_number: The project number.
+        pubsub_topic_name: The name of the pubsub topic to publish to.
+        use_ci: Flag that determines whether to use Cloud CI/CD.
+        workload_identity_pool: Pool for workload identity federation. 
+        workload_identity_provider: Provider for workload identity federation.
+        workload_identity_service_account: Service account for workload identity federation. 
+
+    Returns:
+        str: Contents of github_actions.yaml.
+    """
+    template_file = import_files(GITHUB_ACTIONS_TEMPLATES_PATH) / 'github_actions.yaml.j2'
+    with template_file.open('r', encoding='utf-8') as f:
+        template = Template(f.read())
+        return template.render(
+            artifact_repo_location=artifact_repo_location,
+            artifact_repo_name=artifact_repo_name,
+            component_base_relative_path=COMPONENT_BASE_RELATIVE_PATH,
+            generated_license=GENERATED_LICENSE,
+            generated_parameter_values_path=GENERATED_PARAMETER_VALUES_PATH,
+            naming_prefix=naming_prefix,
+            project_id=project_id,
+            project_number=project_number,
+            pubsub_topic_name=pubsub_topic_name,
+            source_repo_branch=DEFAULT_SOURCE_REPO_BRANCH,
+            use_ci=use_ci,
+            workload_identity_pool=workload_identity_pool,
+            workload_identity_provider=workload_identity_provider,
+            workload_identity_service_account=workload_identity_service_account)
diff --git a/google_cloud_automlops/deployments/github_actions/templates/__init__.py b/google_cloud_automlops/deployments/github_actions/templates/__init__.py
new file mode 100644
index 0000000..2379f87
--- /dev/null
+++ b/google_cloud_automlops/deployments/github_actions/templates/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2023 Google LLC. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/google_cloud_automlops/deployments/github_actions/templates/github_actions.yaml.j2 b/google_cloud_automlops/deployments/github_actions/templates/github_actions.yaml.j2
new file mode 100644
index 0000000..8c66ab6
--- /dev/null
+++ b/google_cloud_automlops/deployments/github_actions/templates/github_actions.yaml.j2
@@ -0,0 +1,83 @@
+{{generated_license}}
+name: 'Build Custom Images for Vertex Pipeline'
+on:
+  push:
+    branches:
+      - '{{source_repo_branch}}'
+
+jobs:
+  deploy: 
+    name: "Image Build, Push, Deploy & Publish PipelineJob"
+    runs-on: ubuntu-latest
+    permissions:
+      id-token: write
+      contents: read
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+
+      # ==============================================================================
+      # Relevant roles for the service account running the pipeline:
+      # - roles/artifactregistry.writer
+      # - roles/pubsub.publisher
+      # - roles/iam.workloadIdentityUser
+      # - roles/storage.admin
+      # ==============================================================================      
+      - name: Google Auth
+        id: auth
+        uses: 'google-github-actions/auth@v0'
+        with:
+          token_format: 'access_token'
+          workload_identity_provider: 'projects/{{project_number}}/locations/global/workloadIdentityPools/{{workload_identity_pool}}/providers/{{workload_identity_provider}}' # e.g. - projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider 
+          service_account: '{{workload_identity_service_account}}'     # e.g. - my-service-account@my-project.iam.gserviceaccount.com
+
+      - name: Set up Cloud SDK
+        id: setup-gcloud
+        uses: 'google-github-actions/setup-gcloud@v1'
+        with:
+          version: '>= 363.0.0'
+  
+      - name: Setup Python
+        id: setup-python
+        uses: actions/setup-python@v4
+        with:
+            python-version: '3.10'
+
+      - name: Docker Auth
+        id: docker-auth
+        uses: 'docker/login-action@v1'
+        with:
+          username: 'oauth2accesstoken'
+          {% raw %}
+          password: '${{ steps.auth.outputs.access_token }}'
+          registry: '{% endraw %}{{ artifact_repo_location }}{% raw %}-docker.pkg.dev' 
+          {% endraw %}
+      # ==============================================================================
+      # BUILD AND PUSH CUSTOM IMAGES
+      # ==============================================================================
+      - name: Build, tag, push base image
+        id: build-push-component-base
+        uses: docker/build-push-action@v3
+        with:
+          context: {{component_base_relative_path}}
+          push: true
+          tags: |
+            {{artifact_repo_location}}-docker.pkg.dev/{{project_id}}/{{artifact_repo_name}}/{{naming_prefix}}/components/component_base:latest
+{% if use_ci %}
+      - name: Install dependencies
+        id: install-pipeline-deps
+        run: | 
+          pip install -r pipelines/requirements.txt --user
+      
+      - name: Build a pipeline spec
+        id: build-pipeline-spec
+        run: python -m pipelines.pipeline --config configs/defaults.yaml
+      
+      - name: Publish PipelineJob to topic
+        id: publish-to-topic
+        shell: bash
+        run: |
+          gcloud pubsub topics publish {{pubsub_topic_name}} --message \
+          "$(cat {{generated_parameter_values_path}})"
+{% endif %}   
+            
diff --git a/google_cloud_automlops/deployments/gitops/git_utils.py b/google_cloud_automlops/deployments/gitops/git_utils.py
index 3c47529..f9ff2db 100644
--- a/google_cloud_automlops/deployments/gitops/git_utils.py
+++ b/google_cloud_automlops/deployments/gitops/git_utils.py
@@ -62,45 +62,40 @@ def git_workflow():
     elif source_repository_type == CodeRepository.BITBUCKET.value:
         git_remote_origin_url = f'''git@bitbucket.org:{defaults['gcp']['source_repository_name']}.git'''
 
-    if not os.path.exists('.git'):
+    if not os.path.exists(f'{BASE_DIR}.git'):
         # Initialize git and configure credentials
-        execute_process('git init', to_null=False)
+        execute_process(f'git -C {BASE_DIR} init', to_null=False)
         if source_repository_type == CodeRepository.CLOUD_SOURCE_REPOSITORIES.value:
             execute_process(
-                '''git config --global credential.'https://source.developers.google.com'.helper gcloud.sh''', to_null=False)
+                f'''git -C {BASE_DIR} config --global credential.'https://source.developers.google.com'.helper gcloud.sh''', to_null=False)
         # Add repo and branch
         execute_process(
-            f'''git remote add origin {git_remote_origin_url}''', to_null=False)
+            f'''git -C {BASE_DIR} remote add origin {git_remote_origin_url}''', to_null=False)
         execute_process(
-            f'''git checkout -B {defaults['gcp']['source_repository_branch']}''', to_null=False)
+            f'''git -C {BASE_DIR} checkout -B {defaults['gcp']['source_repository_branch']}''', to_null=False)
         has_remote_branch = subprocess.check_output(
-            [f'''git ls-remote origin {defaults['gcp']['source_repository_branch']}'''], shell=True, stderr=subprocess.STDOUT)
+            [f'''git -C {BASE_DIR} ls-remote origin {defaults['gcp']['source_repository_branch']}'''], shell=True, stderr=subprocess.STDOUT)
 
+        write_file(f'{BASE_DIR}.gitignore', _create_gitignore_jinja(), 'w')
         # This will initialize the branch, a second push will be required to trigger the cloudbuild job after initializing
         if not has_remote_branch:
-            write_file('.gitignore', _create_gitignore_jinja(), 'w')
-            execute_process('git add .gitignore', to_null=False)
-            execute_process('''git commit -m 'init' ''', to_null=False)
+            execute_process(f'git -C {BASE_DIR} add .gitignore', to_null=False)
+            execute_process(f'''git -C {BASE_DIR} commit -m 'init' ''', to_null=False)
             execute_process(
-                f'''git push origin {defaults['gcp']['source_repository_branch']} --force''', to_null=False)
+                f'''git -C {BASE_DIR} push origin {defaults['gcp']['source_repository_branch']} --force''', to_null=False)
 
     # Check for remote origin url mismatch
     actual_remote = subprocess.check_output(
-        ['git config --get remote.origin.url'], shell=True, stderr=subprocess.STDOUT).decode('utf-8').strip('\n')
+        [f'git -C {BASE_DIR} config --get remote.origin.url'], shell=True, stderr=subprocess.STDOUT).decode('utf-8').strip('\n')
     if actual_remote != git_remote_origin_url:
         raise RuntimeError(
             f'Expected remote origin url {git_remote_origin_url} but found {actual_remote}. Reset your remote origin url to continue.')
 
     # Add, commit, and push changes to CSR
-    execute_process(f'git add {BASE_DIR} ', to_null=False)
-    # Gitlab CI and Github Actions are roadmap items
-    # if deployment_framework == Deployer.GITHUB_ACTIONS.value:
-    #     execute_process('git add .github/workflows/.github-ci.yml ', to_null=False)
-    # elif deployment_framework == Deployer.GITLAB_CI.value:
-    #     execute_process('git add .gitlab-ci.yml ', to_null=False)
-    execute_process('''git commit -m 'Run AutoMLOps' ''', to_null=False)
+    execute_process(f'git -C {BASE_DIR} add .', to_null=False)
+    execute_process(f'''git -C {BASE_DIR} commit -m 'Run AutoMLOps' ''', to_null=False)
     execute_process(
-        f'''git push origin {defaults['gcp']['source_repository_branch']} --force''', to_null=False)
+        f'''git -C {BASE_DIR} push origin {defaults['gcp']['source_repository_branch']} --force''', to_null=False)
     # pylint: disable=logging-fstring-interpolation
     logging.info(
         f'''Pushing code to {defaults['gcp']['source_repository_branch']} branch, triggering build...''')
diff --git a/google_cloud_automlops/deployments/gitops/templates/gitignore.j2 b/google_cloud_automlops/deployments/gitops/templates/gitignore.j2
index 383728e..8c9c1ef 100644
--- a/google_cloud_automlops/deployments/gitops/templates/gitignore.j2
+++ b/google_cloud_automlops/deployments/gitops/templates/gitignore.j2
@@ -85,6 +85,14 @@ target/
 
 # Jupyter Notebook
 .ipynb_checkpoints
+.bashrc
+.config/
+.docker/
+.gitconfig
+.gsutil/
+.jupyter/
+.local/
+.ssh/
 
 # IPython
 profile_default/
diff --git a/google_cloud_automlops/provisioning/gcloud/templates/provision_resources.sh.j2 b/google_cloud_automlops/provisioning/gcloud/templates/provision_resources.sh.j2
index 68c180c..e42c330 100644
--- a/google_cloud_automlops/provisioning/gcloud/templates/provision_resources.sh.j2
+++ b/google_cloud_automlops/provisioning/gcloud/templates/provision_resources.sh.j2
@@ -143,6 +143,7 @@ fi
 echo -e "$GREEN Deploying Cloud Functions: ${PIPELINE_JOB_SUBMISSION_SERVICE_NAME} in project $PROJECT_ID $NC"
 gcloud functions deploy $PIPELINE_JOB_SUBMISSION_SERVICE_NAME \
   --no-allow-unauthenticated \
+  --docker-repository="projects/${PROJECT_ID}/locations/${ARTIFACT_REPO_LOCATION}/repositories/${ARTIFACT_REPO_NAME}" \
   --trigger-topic=$PUBSUB_TOPIC_NAME \
   --entry-point=process_request \
   --runtime=python39 \
@@ -159,12 +160,12 @@ if ! (gcloud beta builds triggers list --project="$PROJECT_ID" --region="$BUILD_
 
   echo "Creating Cloudbuild Trigger on branch $SOURCE_REPO_BRANCH in project $PROJECT_ID for repo ${SOURCE_REPO_NAME}"
   gcloud beta builds triggers create cloud-source-repositories \
-    --included-files=${BASE_DIR}** \
+    --ignored-files=.gitignore \
     --region=$BUILD_TRIGGER_LOCATION \
     --name=$BUILD_TRIGGER_NAME \
     --repo=$SOURCE_REPO_NAME \
     --branch-pattern="$SOURCE_REPO_BRANCH" \
-    --build-config=${BASE_DIR}cloudbuild.yaml
+    --build-config=cloudbuild.yaml
 
 else
 
diff --git a/google_cloud_automlops/provisioning/terraform/builder.py b/google_cloud_automlops/provisioning/terraform/builder.py
index 31e0b99..fa91032 100644
--- a/google_cloud_automlops/provisioning/terraform/builder.py
+++ b/google_cloud_automlops/provisioning/terraform/builder.py
@@ -42,11 +42,15 @@
     TERRAFORM_TEMPLATES_PATH
 )
 
+from google_cloud_automlops.deployments.enums import (
+    Deployer
+)
+
 from google_cloud_automlops.provisioning.configs import TerraformConfig
 
 def build(
     project_id: str,
-    config: TerraformConfig,
+    config: TerraformConfig
 ):
     """Constructs and writes terraform scripts: Generates infrastructure using terraform hcl resource management style.
 
@@ -106,25 +110,47 @@ def build(
     # create environment/variables.tf
     write_file(f'{BASE_DIR}provision/environment/variables.tf', create_environment_variables_tf_jinja(), 'w')
     # create environment/variables.auto.tfvars
-    write_file(f'{BASE_DIR}provision/environment/variables.auto.tfvars', create_environment_variables_auto_tfvars_jinja(
-        artifact_repo_location=config.artifact_repo_location,
-        artifact_repo_name=config.artifact_repo_name,
-        build_trigger_location=config.build_trigger_location,
-        build_trigger_name=config.build_trigger_name,
-        pipeline_job_runner_service_account=config.pipeline_job_runner_service_account,
-        pipeline_job_submission_service_location=config.pipeline_job_submission_service_location,
-        pipeline_job_submission_service_name=config.pipeline_job_submission_service_name,
-        project_id=project_id,
-        provision_credentials_key=config.provision_credentials_key,
-        pubsub_topic_name=config.pubsub_topic_name,
-        schedule_location=config.schedule_location,
-        schedule_name=config.schedule_name,
-        schedule_pattern=config.schedule_pattern,
-        source_repo_branch=config.source_repo_branch,
-        source_repo_name=config.source_repo_name,
-        storage_bucket_location=config.storage_bucket_location,
-        storage_bucket_name=config.storage_bucket_name,
-        vpc_connector=config.vpc_connector), 'w')
+    if config.deployment_framework == Deployer.CLOUDBUILD.value:
+        write_file(f'{BASE_DIR}provision/environment/variables.auto.tfvars', create_environment_variables_auto_tfvars_jinja(
+            artifact_repo_location=config.artifact_repo_location,
+            artifact_repo_name=config.artifact_repo_name,
+            build_trigger_location=config.build_trigger_location,
+            build_trigger_name=config.build_trigger_name,
+            pipeline_job_runner_service_account=config.pipeline_job_runner_service_account,
+            pipeline_job_submission_service_location=config.pipeline_job_submission_service_location,
+            pipeline_job_submission_service_name=config.pipeline_job_submission_service_name,
+            project_id=project_id,
+            provision_credentials_key=config.provision_credentials_key,
+            pubsub_topic_name=config.pubsub_topic_name,
+            schedule_location=config.schedule_location,
+            schedule_name=config.schedule_name,
+            schedule_pattern=config.schedule_pattern,
+            source_repo_branch=config.source_repo_branch,
+            source_repo_name=config.source_repo_name,
+            storage_bucket_location=config.storage_bucket_location,
+            storage_bucket_name=config.storage_bucket_name,
+            vpc_connector=config.vpc_connector), 'w')
+    #TODO: implement workload identity as optional
+    if config.deployment_framework == Deployer.GITHUB_ACTIONS.value:
+        write_file(f'{BASE_DIR}provision/environment/variables.auto.tfvars', create_environment_variables_auto_tfvars_jinja(
+            artifact_repo_location=config.artifact_repo_location,
+            artifact_repo_name=config.artifact_repo_name,
+            build_trigger_location=config.build_trigger_location,
+            build_trigger_name=config.build_trigger_name,
+            pipeline_job_runner_service_account=config.pipeline_job_runner_service_account,
+            pipeline_job_submission_service_location=config.pipeline_job_submission_service_location,
+            pipeline_job_submission_service_name=config.pipeline_job_submission_service_name,
+            project_id=project_id,
+            provision_credentials_key=config.provision_credentials_key,
+            pubsub_topic_name=config.pubsub_topic_name,
+            schedule_location=config.schedule_location,
+            schedule_name=config.schedule_name,
+            schedule_pattern=config.schedule_pattern,
+            source_repo_branch=config.source_repo_branch,
+            source_repo_name=config.source_repo_name,
+            storage_bucket_location=config.storage_bucket_location,
+            storage_bucket_name=config.storage_bucket_name,
+            vpc_connector=config.vpc_connector), 'w')
     # create environment/versions.tf
     write_file(f'{BASE_DIR}provision/environment/versions.tf', create_environment_versions_tf_jinja(storage_bucket_name=config.storage_bucket_name), 'w')
     # create provision_resources.sh
diff --git a/google_cloud_automlops/provisioning/terraform/templates/environment/main.tf.j2 b/google_cloud_automlops/provisioning/terraform/templates/environment/main.tf.j2
index 04ffe76..88854e5 100644
--- a/google_cloud_automlops/provisioning/terraform/templates/environment/main.tf.j2
+++ b/google_cloud_automlops/provisioning/terraform/templates/environment/main.tf.j2
@@ -110,7 +110,7 @@ resource "google_storage_bucket_object" "archive_submission_service_code" {
 resource "google_cloudfunctions_function" "pipeline_job_submission_service" {
   name                  = var.pipeline_job_submission_service_name
   region                = var.pipeline_job_submission_service_location
-# docker_registry       = "ARTIFACT_REGISTRY"
+  docker_repository     = "projects/${var.project_id}/locations/${var.artifact_repo_location}/repositories/${var.artifact_repo_name}"
   service_account_email = google_service_account.pipeline_job_runner_service_account.email
   runtime               = "python39"
   entry_point           = "process_request"
@@ -124,7 +124,7 @@ resource "google_cloudfunctions_function" "pipeline_job_submission_service" {
     resource            = "projects/${var.project_id}/topics/${var.pubsub_topic_name}"
   }
 
-  depends_on            = [google_pubsub_topic.pubsub_topic]
+  depends_on            = [google_artifact_registry_repository.artifact_registry, google_pubsub_topic.pubsub_topic]
 }{% endif %}
 {% if deployment_framework == 'cloud-build' and source_repo_type == 'cloud-source-repositories' %}
 # Create Cloud Build Trigger
@@ -132,13 +132,13 @@ resource "google_cloudbuild_trigger" "cloudbuild_trigger" {
   project                 = var.project_id
   name                    = var.build_trigger_name
   location                = var.build_trigger_location
-  included_files          = ["{{base_dir}}**"]
+  ignored-files           = [".gitignore"]
   trigger_template {
     branch_name           = var.source_repo_branch
     project_id            = var.project_id
     repo_name             = var.source_repo_name
   }
-  filename                = "{{base_dir}}cloudbuild.yaml"
+  filename                = "cloudbuild.yaml"
 
   depends_on              = [google_sourcerepo_repository.source_repo]
 }{% endif %}
diff --git a/google_cloud_automlops/utils/constants.py b/google_cloud_automlops/utils/constants.py
index 8524186..b3c8750 100644
--- a/google_cloud_automlops/utils/constants.py
+++ b/google_cloud_automlops/utils/constants.py
@@ -58,6 +58,7 @@
 
 # AutoMLOps file paths
 BASE_DIR = 'AutoMLOps/'
+GITHUB_DIR = BASE_DIR + '.github/workflows/'
 GENERATED_DEFAULTS_FILE = BASE_DIR + 'configs/defaults.yaml'
 GENERATED_PIPELINE_SPEC_SH_FILE = BASE_DIR + 'scripts/build_pipeline_spec.sh'
 GENERATED_BUILD_COMPONENTS_SH_FILE = BASE_DIR + 'scripts/build_components.sh'
@@ -66,15 +67,18 @@
 GENERATED_RESOURCES_SH_FILE = BASE_DIR + 'provision/provision_resources.sh'
 GENERATED_PUBLISH_TO_TOPIC_FILE = BASE_DIR + 'scripts/publish_to_topic.sh'
 GENERATED_CLOUDBUILD_FILE = BASE_DIR + 'cloudbuild.yaml'
+GENERATED_GITHUB_ACTIONS_FILE = GITHUB_DIR + 'github_actions.yaml'
 GENERATED_PIPELINE_REQUIREMENTS_FILE = BASE_DIR + 'pipelines/requirements.txt'
 GENERATED_PIPELINE_FILE = BASE_DIR + 'pipelines/pipeline.py'
 GENERATED_PIPELINE_RUNNER_FILE = BASE_DIR + 'pipelines/pipeline_runner.py'
 GENERATED_COMPONENT_BASE = BASE_DIR + 'components/component_base'
 GENERATED_COMPONENT_BASE_SRC = BASE_DIR + 'components/component_base/src'
+COMPONENT_BASE_RELATIVE_PATH = 'components/component_base'
 GENERATED_PARAMETER_VALUES_PATH = 'pipelines/runtime_parameters/pipeline_parameter_values.json'
 GENERATED_PIPELINE_JOB_SPEC_PATH = 'scripts/pipeline_spec/pipeline_job.json'
 GENERATED_DIRS = [
     BASE_DIR,
+    GITHUB_DIR,
     BASE_DIR + 'components',
     BASE_DIR + 'components/component_base',
     BASE_DIR + 'components/component_base/src',
@@ -116,6 +120,7 @@
 GCLOUD_TEMPLATES_PATH = 'google_cloud_automlops.provisioning.gcloud.templates'
 KFP_TEMPLATES_PATH = 'google_cloud_automlops.orchestration.kfp.templates'
 CLOUDBUILD_TEMPLATES_PATH = 'google_cloud_automlops.deployments.cloudbuild.templates'
+GITHUB_ACTIONS_TEMPLATES_PATH = 'google_cloud_automlops.deployments.github_actions.templates'
 GITOPS_TEMPLATES_PATH = 'google_cloud_automlops.deployments.gitops.templates'
 
 # Required IAM Roles for pipeline runner service account
diff --git a/google_cloud_automlops/utils/utils.py b/google_cloud_automlops/utils/utils.py
index 12d0fdf..62c742d 100644
--- a/google_cloud_automlops/utils/utils.py
+++ b/google_cloud_automlops/utils/utils.py
@@ -462,6 +462,7 @@ def get_required_apis(defaults: dict) -> Set:
         set: The set of required APIs
     """
     required_apis = set([
+        'cloudbuild.googleapis.com',
         'cloudresourcemanager.googleapis.com',
         'compute.googleapis.com',
         'iamcredentials.googleapis.com',
@@ -472,8 +473,8 @@ def get_required_apis(defaults: dict) -> Set:
         required_apis.add('aiplatform.googleapis.com')
     if defaults['gcp']['artifact_repo_type'] == ArtifactRepository.ARTIFACT_REGISTRY.value:
         required_apis.add('artifactregistry.googleapis.com')
-    if defaults['tooling']['deployment_framework'] == Deployer.CLOUDBUILD.value:
-        required_apis.add('cloudbuild.googleapis.com')
+    # if defaults['tooling']['deployment_framework'] == Deployer.CLOUDBUILD.value:
+    #     required_apis.add('cloudbuild.googleapis.com')
     if defaults['gcp']['schedule_pattern'] != DEFAULT_SCHEDULE_PATTERN:
         required_apis.add('cloudscheduler.googleapis.com')
     if defaults['gcp']['pipeline_job_submission_service_type'] == PipelineJobSubmitter.CLOUD_RUN.value:
diff --git a/setup.py b/setup.py
index 502baf3..01f3652 100644
--- a/setup.py
+++ b/setup.py
@@ -20,7 +20,7 @@
 
 setup(
     name='google-cloud-automlops',
-    version='1.2.2',
+    version='1.2.3',
     description='Build MLOps Pipelines in Minutes.',
     long_description=readme_contents,
     long_description_content_type='text/markdown',


Test patch:
diff --git a/tests/unit/deployments/github_actions/.gitkeep b/tests/unit/deployments/github_actions/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/unit/deployments/github_actions/__init__.py b/tests/unit/deployments/github_actions/__init__.py
new file mode 100644
index 0000000..2379f87
--- /dev/null
+++ b/tests/unit/deployments/github_actions/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2023 Google LLC. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
diff --git a/tests/unit/deployments/github_actions/builder_test.py b/tests/unit/deployments/github_actions/builder_test.py
new file mode 100644
index 0000000..93d3bfa
--- /dev/null
+++ b/tests/unit/deployments/github_actions/builder_test.py
@@ -0,0 +1,112 @@
+# Copyright 2023 Google LLC. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# pylint: disable=line-too-long
+# pylint: disable=missing-function-docstring
+# pylint: disable=missing-module-docstring
+
+from typing import List
+
+import pytest
+
+from google_cloud_automlops.deployments.github_actions.builder import create_github_actions_jinja
+
+
+@pytest.mark.parametrize(
+    '''artifact_repo_location, artifact_repo_name, naming_prefix,'''
+    '''project_id, project_number, pubsub_topic_name, use_ci, workload_identity_provider,'''
+    ''' workload_identity_pool, workload_identity_service_account, is_included,'''
+    '''expected_output_snippets''',
+    [
+        (
+            'us-central1', 'my-artifact-repo', 'my-prefix',
+            'my-project', 'my-project-number', 'my-topic', True, 'my-provider',
+            'my-pool', 'my-sa', True,
+            ['id: auth',
+             'id: build-push-component-base',
+             'id: install-pipeline-deps',
+             'id: build-pipeline-spec',
+             'id: publish-to-topic', 
+             'us-central1-docker.pkg.dev/my-project/my-artifact-repo/my-prefix/components/component_base:latest',
+             'gcloud pubsub topics publish my-topic --message']
+        ),
+        (
+            'us-central1', 'my-artifact-repo', 'my-prefix',
+            'my-project', 'my-project-number', 'my-topic', False,  'my-provider',
+            'my-pool', 'my-sa', True,
+            ['id: build-push-component-base',
+             'us-central1-docker.pkg.dev/my-project/my-artifact-repo/my-prefix/components/component_base:latest']
+        ),
+        (
+            'us-central1', 'my-artifact-repo', 'my-prefix',
+            'my-project', 'my-project-number', 'my-topic', False,  'my-provider',
+            'my-pool', 'my-sa', False,
+            ['id: install-pipeline-deps',
+             'id: build-pipeline-spec',
+             'id: publish-to-topic',
+             'gcloud pubsub topics publish my-topic --message']
+        ),
+    ]
+)
+def test_create_github_actions_jinja(
+    artifact_repo_location: str,
+    artifact_repo_name: str,
+    naming_prefix: str,
+    project_id: str,
+    project_number: str,
+    pubsub_topic_name: str,
+    use_ci: bool,
+    workload_identity_pool: str,
+    workload_identity_provider: str,
+    workload_identity_service_account: str,
+    is_included: bool,
+    expected_output_snippets: List[str]):
+    """Tests create_github_actions_jinja, which generates content for the github actions file. 
+       There are three test cases for this function:
+        1. Checks that expected strings are included when use_ci=True. 
+        2. Checks that expected strings are included when use_ci=False. 
+        3. Checks that certain strings are not included when use_ci=False. 
+
+    Args:
+        artifact_repo_location: Region of the artifact repo (default use with Artifact Registry).
+        artifact_repo_name: Artifact repo name where components are stored (default use with Artifact Registry).
+        naming_prefix: Unique value used to differentiate pipelines and services across AutoMLOps runs.
+        project_id: The project ID.
+        project_number: The project number.
+        pubsub_topic_name: The name of the pubsub topic to publish to.
+        use_ci: Flag that determines whether to use Cloud CI/CD.
+        workload_identity_pool: Pool for workload identity federation. 
+        workload_identity_provider: Provider for workload identity federation.
+        workload_identity_service_account: Service account for workload identity federation. 
+        is_included: Boolean that determines whether to check if the expected_output_snippets exist in the string or not.
+        expected_output_snippets: Strings that are expected to be included (or not) based on the is_included boolean.
+    """
+
+    github_actions_config = create_github_actions_jinja(
+        artifact_repo_location,
+        artifact_repo_name,
+        naming_prefix,
+        project_id,
+        project_number,
+        pubsub_topic_name,
+        use_ci,
+        workload_identity_pool,
+        workload_identity_provider,
+        workload_identity_service_account)
+
+    for snippet in expected_output_snippets:
+        if is_included:
+            assert snippet in github_actions_config
+        elif not is_included:
+            assert snippet not in github_actions_config