{"id":4101,"date":"2025-03-08T18:03:18","date_gmt":"2025-03-08T18:03:18","guid":{"rendered":"https:\/\/code2deploy.com\/blog\/?p=4101"},"modified":"2025-03-08T18:03:18","modified_gmt":"2025-03-08T18:03:18","slug":"github-actions-complete-step-by-step-guide","status":"publish","type":"post","link":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/","title":{"rendered":"GitHub Actions: Complete Step-by-Step Guide"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\"><strong>1. Introduction to GitHub Actions<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What is GitHub Actions?<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">GitHub Actions is a CI\/CD (Continuous Integration and Continuous Deployment) tool that allows developers to automate workflows directly in their GitHub repository. It helps automate software development processes like testing, building, and deploying applications.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Why Use GitHub Actions?<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Automate repetitive tasks in software development.<\/li>\n\n\n\n<li>Run tests automatically after every push.<\/li>\n\n\n\n<li>Deploy applications seamlessly.<\/li>\n\n\n\n<li>Manage workflows with GitHub-hosted or self-hosted runners.<\/li>\n\n\n\n<li>Integrate with third-party services (Docker, Kubernetes, AWS, etc.).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Use Cases<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>CI\/CD Pipelines<\/strong>: Automate testing, building, and deployment.<\/li>\n\n\n\n<li><strong>Code Quality Checks<\/strong>: Run linters and security scans on every push.<\/li>\n\n\n\n<li><strong>Automated Releases<\/strong>: Publish artifacts to package managers.<\/li>\n\n\n\n<li><strong>Infrastructure as Code (IaC)<\/strong>: Deploy infrastructure using Terraform, Ansible, or Kubernetes.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Hosted Runners vs. Self-Hosted Runners<\/strong><\/h3>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Hosted Runners<\/strong><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">GitHub provides virtual machines (VMs) that run jobs in a workflow. Examples:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ubuntu-latest<\/li>\n\n\n\n<li>windows-latest<\/li>\n\n\n\n<li>macos-latest<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Self-Hosted Runners<\/strong><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">A self-hosted runner allows you to run workflows on your own infrastructure, giving you more control over the environment and resource allocation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A GitHub Actions workflow consists of:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>name<\/strong> \u2013 Workflow display name.<\/li>\n\n\n\n<li><strong>on<\/strong> \u2013 Defines when the workflow should run (events like push, pull_request, or schedule).<\/li>\n\n\n\n<li><strong>env<\/strong> \u2013 Sets environment variables.<\/li>\n\n\n\n<li><strong>jobs<\/strong> \u2013 Defines a list of jobs (each job runs independently).<\/li>\n\n\n\n<li><strong>steps<\/strong> \u2013 Tasks executed in a job (e.g., checking out code, running scripts).<\/li>\n\n\n\n<li><strong>needs<\/strong> \u2013 Specifies job dependencies; ensures a job runs only after another completes.<\/li>\n\n\n\n<li><strong>runs-on<\/strong> \u2013 Defines the virtual machine environment for the job (e.g., ubuntu-latest, macos-latest).<\/li>\n\n\n\n<li><strong>container<\/strong> \u2013 Runs jobs inside a specified container instead of the default virtual environment.<\/li>\n\n\n\n<li><strong>services<\/strong> \u2013 Defines additional containers for services like databases (e.g., Redis, MySQL).<\/li>\n\n\n\n<li><strong>timeout-minutes<\/strong> \u2013 Maximum execution time before GitHub cancels the job.<\/li>\n\n\n\n<li><strong>strategy<\/strong> \u2013 Defines a build matrix to run jobs with different configurations (e.g., multiple OS or Node.js versions).<\/li>\n\n\n\n<li><strong>fail-fast<\/strong> \u2013 Stops all in-progress matrix jobs if one fails.<\/li>\n\n\n\n<li><strong>uses<\/strong> \u2013 Runs an action from a public\/private repository or Docker image.<\/li>\n\n\n\n<li><strong>with<\/strong> \u2013 Provides input parameters for actions.<\/li>\n\n\n\n<li><strong>if<\/strong> \u2013 Conditional execution of a step or job based on an expression.<\/li>\n\n\n\n<li><strong>run<\/strong> \u2013 Executes shell commands directly in a step.<\/li>\n\n\n\n<li><strong>artifact storage<\/strong> \u2013 Stores and shares files between jobs using upload-artifact and download-artifact.<\/li>\n\n\n\n<li><strong>caching<\/strong> \u2013 Speeds up workflows by caching dependencies with actions\/cache.<\/li>\n\n\n\n<li><strong>context and expressions<\/strong> \u2013 Uses expressions (${{ }}) to reference variables, secrets, and runtime information.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the structured, parent-child syntax sequence for GitHub Actions workflow components, with each component explained in terms of its relationship to others. This will give you a tree structure to help understand how these parts fit together:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>Workflow<br>&nbsp; \u251c\u2500\u2500 name &nbsp; &nbsp; &nbsp; &nbsp; # (Parent: Workflow) &#8211; Display name of the workflow.<br>&nbsp; \u251c\u2500\u2500 on &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # (Parent: Workflow) &#8211; Defines when the workflow runs (e.g., push, pull_request).<br>&nbsp; \u2502 &nbsp; &nbsp; \u2514\u2500\u2500 push#(Child:on)-Examp of an event that triggers the workflow when a push is made to a branch.<br>&nbsp; \u2502 &nbsp; &nbsp; \u2514\u2500\u2500 pull_request#(Child:on)-Example of an event that triggers the workflow on a pull request.<br>&nbsp; \u251c\u2500\u2500 env # (Parent: Workflow) &#8211; Sets environment variables accessible throughout the workflow.<br>&nbsp; \u251c\u2500\u2500 jobs # (Parent: Workflow) &#8211; Defines the jobs in the workflow.<br>&nbsp; \u2502 &nbsp; &nbsp; \u2514\u2500\u2500 job_name # (Child: jobs) &#8211; Each job that runs in parallel or sequentially.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u251c\u2500\u2500 runs-on #(Parent:job_name)-Defines the VM environment for the job (e.g., ubuntu-latest).<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u251c\u2500\u2500 container # (Parent: job_name) &#8211; Specifies if the job should run inside a container.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u251c\u2500\u2500 services # (Parent:job_name)-Defines services (Redis, MySQL) required for the job.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u251c\u2500\u2500 timeout-minutes # (Parent: job_name) &#8211; Defines the max execution time for the job.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u251c\u2500\u2500 strategy #(Parent:job_name)-Defines a build matrix to run jobs with multiple config.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u2502 &nbsp; &nbsp; \u2514\u2500\u2500 matrix # (Child: strategy)-Matrix configurations (e.g., multiple OS or versions).<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u251c\u2500\u2500 steps # (Parent: job_name) &#8211; The list of steps to execute in the job.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u2502 &nbsp; &nbsp; \u251c\u2500\u2500 name # (Parent: steps) &#8211; Descriptive name for each step.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u2502 &nbsp; &nbsp; \u251c\u2500\u2500 uses # (Parent:steps)-Runs an action from a pub\/private repo or Docker image.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u2502 &nbsp; &nbsp; \u251c\u2500\u2500 with # (Parent: steps) &#8211; Input parameters for the action.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u2502 &nbsp; &nbsp; \u251c\u2500\u2500 run&nbsp; # (Parent: steps) &#8211; Run shell commands directly in the step.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u2502 &nbsp; &nbsp; \u251c\u2500\u2500 if &nbsp; # (Parent: steps) &#8211; Conditional execution of a step based on expressions.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u2502 &nbsp; &nbsp; \u251c\u2500\u2500 artifact storage#(Parent:steps)-Defines storage,upload-artf, download-artifact.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u2502 &nbsp; &nbsp; \u251c\u2500\u2500 caching&nbsp; # (Parent: steps) &#8211; Caches dependencies with actions\/cache.<br>&nbsp; \u2502&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \u2502 &nbsp; &nbsp; \u2514\u2500\u2500 context and expressions #(Parent:steps)Uses expressions for dynamic variables, secrets, etc.<br>&nbsp; \u2514\u2500\u2500 needs # (Parent: Workflow, job_name) &#8211; Specifies job dependencies, ensuring jobs run in order.<br>&nbsp; &nbsp; &nbsp; &nbsp; \u2514\u2500\u2500 job_name # (Child: needs) &#8211; The job that must finish before the current job can run.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>2. Understanding GitHub Actions Workflow Syntax<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A GitHub Actions workflow is defined using YAML files stored in .github\/workflows\/.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here are practical examples for each component of the GitHub Actions workflow, with explanations for each parent-child relationship:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>1. <\/strong><strong>name<\/strong><strong> <\/strong>(Parent: Workflow) &#8211; Display name of the workflow<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This is the name of your workflow.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>name: CI\/CD Pipeline<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>2. <\/strong><strong>on<\/strong><strong> <\/strong>(Parent: Workflow) &#8211; Defines when the workflow runs (e.g., push, pull_request)<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>on:<br>&nbsp; push:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # (Child: on) &#8211; Trigger when a push is made to a branch<br>&nbsp; &nbsp; branches:<br>&nbsp; &nbsp; &nbsp; &#8211; main &nbsp; &nbsp; # Trigger only when changes are pushed to the &#8216;main&#8217; branch<br>&nbsp; pull_request:&nbsp; # (Child: on) &#8211; Trigger when a pull request is created or updated<br>&nbsp; &nbsp; branches:<br>&nbsp; &nbsp; &nbsp; &#8211; main &nbsp; &nbsp; # Trigger for pull requests targeting the &#8216;main&#8217; branch<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>3. <\/strong><strong>env<\/strong><strong> <\/strong>(Parent: Workflow) &#8211; Sets environment variables accessible throughout the workflow<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>env:<br>&nbsp; GLOBAL_ENV_VAR: value &nbsp; # Global environment variable available in all jobs<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>4. <\/strong><strong>jobs<\/strong><strong> (<\/strong>Parent: Workflow) &#8211; Defines the jobs in the workflow<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Each job can be executed independently.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>jobs:<br>&nbsp; build:&nbsp; # (Child: jobs) &#8211; The &#8216;build&#8217; job defined here<br>&nbsp; &nbsp; runs-on: ubuntu-latest&nbsp; # (Parent: job_name) &#8211; Specifies the virtual environment for the job<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>5. <\/strong><strong>runs-on<\/strong><strong> <\/strong>(Parent: job_name) &#8211; Defines the virtual machine environment for the job<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>jobs:<br>&nbsp; build:<br>&nbsp; &nbsp; runs-on: ubuntu-latest&nbsp; # (Parent: job_name) &#8211; Runs the build job on the latest Ubuntu environment<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>6. <\/strong><strong>container<\/strong><strong> <\/strong>(Parent: job_name) &#8211; Specifies if the job should run inside a container<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>jobs:<br>&nbsp; build:<br>&nbsp; &nbsp; container:<br>&nbsp; &nbsp; &nbsp; image: node:16&nbsp; # (Parent: job_name) &#8211; Use Node.js version 16 inside a Docker container<br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; &#8211; name: Checkout code<br>&nbsp; &nbsp; &nbsp; &nbsp; uses: actions\/checkout@v2<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>7. <\/strong><strong>services<\/strong><strong> <\/strong>(Parent: job_name) &#8211; Defines services like databases required for the job<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>jobs:<br>&nbsp; build:<br>&nbsp; &nbsp; services:<br>&nbsp; &nbsp; &nbsp; redis:&nbsp; # (Parent: job_name) &#8211; A Redis service required for the job<br>&nbsp; &nbsp; &nbsp; &nbsp; image: redis:alpine<br>&nbsp; &nbsp; &nbsp; &nbsp; ports:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8211; 6379:6379<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>8. <\/strong><strong>timeout-minutes<\/strong><strong> <\/strong>(Parent: job_name) &#8211; Defines the max execution time for the job<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>jobs:<br>&nbsp; build:<br>&nbsp; &nbsp; timeout-minutes: 30&nbsp; # (Parent: job_name) &#8211; Set the timeout to 30 minutes for the build job<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>9. <\/strong><strong>strategy<\/strong><strong> <\/strong>(Parent: job_name) &#8211; Defines a build matrix to run jobs with multiple configurations<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>jobs:<br>&nbsp; build:<br>&nbsp; &nbsp; strategy:<br>&nbsp; &nbsp; &nbsp; matrix:<br>&nbsp; &nbsp; &nbsp; &nbsp; os: [ubuntu-latest, macos-latest]&nbsp; # (Child: strategy) &#8211; Run the job on both Ubuntu and macOS<br>&nbsp; &nbsp; &nbsp; &nbsp; node_version: [14, 16] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # (Child: strategy) &#8211; Test with Node.js versions 14 and 16<br>&nbsp; &nbsp; runs-on: ${{ matrix.os }}&nbsp; # Use the OS defined in the matrix<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>10. <\/strong><strong>matrix<\/strong><strong> <\/strong>(Child: strategy) &#8211; Matrix configurations (e.g., multiple OS or versions)<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>strategy:<br>&nbsp; matrix:<br>&nbsp; &nbsp; os: [ubuntu-latest, macos-latest]&nbsp; # (Child: strategy) &#8211; Define the OS configurations<br>&nbsp; &nbsp; node_version: [14, 16] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # (Child: strategy) &#8211; Define the Node.js versions to test<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>11. <\/strong><strong>steps<\/strong><strong> <\/strong>(Parent: job_name) &#8211; The list of steps to execute in the job<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>jobs:<br>&nbsp; build:<br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; &#8211; name: Checkout code&nbsp; # (Parent: steps) &#8211; Check out the code repository<br>&nbsp; &nbsp; &nbsp; &nbsp; uses: actions\/checkout@v2<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>12. <\/strong><strong>name<\/strong><strong> <\/strong>(Parent: steps) &#8211; Descriptive name for each step<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>steps:<br>&nbsp; &#8211; name: Checkout repository&nbsp; # (Parent: steps) &#8211; This is a descriptive name for the step<br>&nbsp; &nbsp; uses: actions\/checkout@v2<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>13. <\/strong><strong>uses<\/strong><strong> <\/strong>(Parent: steps) &#8211; Runs an action from a public\/private repository or Docker image<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>steps:<br>&nbsp; &#8211; name: Set up Node.js&nbsp; # (Parent: steps) &#8211; Set up the Node.js environment<br>&nbsp; &nbsp; uses: actions\/setup-node@v2&nbsp; # (Parent: steps) &#8211; Uses the setup-node action<br>&nbsp; &nbsp; with:<br>&nbsp; &nbsp; &nbsp; node-version: &#8217;16&#8217;&nbsp; # (Parent: steps) &#8211; Specify Node.js version<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>14. <\/strong><strong>with<\/strong><strong> <\/strong>(Parent: steps) &#8211; Input parameters for the action<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>steps:<br>&nbsp; &#8211; name: Set up Node.js<br>&nbsp; &nbsp; uses: actions\/setup-node@v2<br>&nbsp; &nbsp; with:<br>&nbsp; &nbsp; &nbsp; node-version: &#8217;16&#8217;&nbsp; # (Parent: steps) &#8211; Specify Node.js version<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>15. <\/strong><strong>run<\/strong><strong> <\/strong>(Parent: steps) &#8211; Executes shell commands directly in the step<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>steps:<br>&nbsp; &#8211; name: Install dependencies&nbsp; # (Parent: steps) &#8211; Install dependencies for the project<br>&nbsp; &nbsp; run: npm install&nbsp; # (Parent: steps) &#8211; Run the shell command to install dependencies<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>16. <\/strong><strong>if<\/strong><strong> <\/strong>(Parent: steps) &#8211; Conditional execution of a step based on expressions<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>steps:<br>&nbsp; &#8211; name: Run tests&nbsp; # (Parent: steps) &#8211; Run tests conditionally<br>&nbsp; &nbsp; if: ${{ success() }}&nbsp; # (Parent: steps) &#8211; Only run this step if the previous step was successful<br>&nbsp; &nbsp; run: npm test<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>17. <\/strong><strong>artifact storage<\/strong> (Parent: steps) &#8211; Defines artifact storage, e.g., upload-artifact, download-artifact<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>steps:<br>&nbsp; &#8211; name: Upload build artifact&nbsp; # (Parent: steps) &#8211; Upload build artifacts for later use<br>&nbsp; &nbsp; uses: actions\/upload-artifact@v2<br>&nbsp; &nbsp; with:<br>&nbsp; &nbsp; &nbsp; name: build-artifact<br>&nbsp; &nbsp; &nbsp; path: .\/build\/output&nbsp; # (Parent: steps) &#8211; Upload the files from the &#8216;output&#8217; directory<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>18. <\/strong><strong>caching<\/strong><strong> <\/strong>(Parent: steps) &#8211; Caches dependencies with actions\/cache<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>steps:<br>&nbsp; &#8211; name: Cache Node.js dependencies&nbsp; # (Parent: steps) &#8211; Cache dependencies for faster builds<br>&nbsp; &nbsp; uses: actions\/cache@v2<br>&nbsp; &nbsp; with:<br>&nbsp; &nbsp; &nbsp; path: node_modules&nbsp; # (Parent: steps) &#8211; Cache the &#8216;node_modules&#8217; folder<br>&nbsp; &nbsp; &nbsp; key: ${{ runner.os }}-node-modules-${{ hashFiles(&#8216;**\/package-lock.json&#8217;) }}&nbsp; # (Parent: steps) &#8211; Cache key based on package-lock.json<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>19. <\/strong><strong>context and expressions<\/strong><strong> <\/strong>(Parent: steps) &#8211; Uses expressions for dynamic variables, secrets, etc.<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>steps:<br>&nbsp; &#8211; name: Deploy to production&nbsp; # (Parent: steps) &#8211; Deploy to production only if it&#8217;s the main branch<br>&nbsp; &nbsp; if: github.ref == &#8216;refs\/heads\/main&#8217;&nbsp; # (Parent: steps) &#8211; Run this step only if the branch is &#8216;main&#8217;<br>&nbsp; &nbsp; run: |<br>&nbsp; &nbsp; &nbsp; scp -i ${{ secrets.SSH_KEY }} .\/build user@server:\/path\/to\/deploy&nbsp; # (Parent: steps) &#8211; Use SSH secret to deploy<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>20. <\/strong><strong>needs<\/strong> (Parent: Workflow, job_name) &#8211; Specifies job dependencies, ensuring jobs run in order<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>jobs:<br>&nbsp; build:<br>&nbsp; &nbsp; runs-on: ubuntu-latest<br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; &#8211; name: Checkout code<br>&nbsp; &nbsp; &nbsp; &nbsp; uses: actions\/checkout@v2<br><br>&nbsp; deploy:<br>&nbsp; &nbsp; needs: build&nbsp; # (Parent: needs) &#8211; This job will only run after &#8216;build&#8217; job completes<br>&nbsp; &nbsp; runs-on: ubuntu-latest<br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; &#8211; name: Deploy application<br>&nbsp; &nbsp; &nbsp; &nbsp; run: echo &#8220;Deploying to server&#8221;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>21. <\/strong><strong>job_name<\/strong><strong> (Child: needs) &#8211; The job that must finish before the current job can run<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>jobs:<br>&nbsp; build:<br>&nbsp; &nbsp; runs-on: ubuntu-latest<br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; &#8211; name: Build project<br>&nbsp; &nbsp; &nbsp; &nbsp; run: npm run build<br><br>&nbsp; deploy:<br>&nbsp; &nbsp; needs: build&nbsp; # (Child: needs) &#8211; The &#8216;deploy&#8217; job depends on the &#8216;build&#8217; job<br>&nbsp; &nbsp; runs-on: ubuntu-latest<br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; &#8211; name: Deploy to production<br>&nbsp; &nbsp; &nbsp; &nbsp; run: npm run deploy<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">These individual examples should give you a clear understanding of each component and how it fits together in a GitHub Actions workflow. You can copy these into a .yml file and experiment with them to build your practical understanding.<strong><\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3. Step-by-Step Practical Guide<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 1: Creating a Simple GitHub Actions Workflow<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Navigate to your GitHub repository.<\/li>\n\n\n\n<li>Create a .github\/workflows\/ directory.<\/li>\n\n\n\n<li>Create a new workflow file, e.g., ci.yml.<\/li>\n\n\n\n<li>Add the following basic workflow:<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>name: Simple CI<br>on: push<br>jobs:<br>&nbsp; build:<br>&nbsp; &nbsp; runs-on: ubuntu-latest<br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; &#8211; name: Checkout Code<br>&nbsp; &nbsp; &nbsp; &nbsp; uses: actions\/checkout@v3<br>&nbsp; &nbsp; &nbsp; &#8211; name: Print Message<br>&nbsp; &nbsp; &nbsp; &nbsp; run: echo &#8220;Build Successful!&#8221;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 2: Running Jobs in a Self-Hosted Runner<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Install a GitHub self-hosted runner on your machine.<\/li>\n\n\n\n<li>Register the runner in GitHub.<\/li>\n\n\n\n<li>Use it in a workflow:<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>jobs:<br>&nbsp; self_hosted_build:<br>&nbsp; &nbsp; runs-on: self-hosted<br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; &#8211; name: Print Machine Name<br>&nbsp; &nbsp; &nbsp; &nbsp; run: hostname<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 3: Running Tests in Docker<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>jobs:<br>&nbsp; test:<br>&nbsp; &nbsp; runs-on: ubuntu-latest<br>&nbsp; &nbsp; container:<br>&nbsp; &nbsp; &nbsp; image: python:3.9<br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; &#8211; name: Run Python Test<br>&nbsp; &nbsp; &nbsp; &nbsp; run: python &#8211;version<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 4: Deploying to Kubernetes<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>jobs:<br>&nbsp; deploy:<br>&nbsp; &nbsp; runs-on: ubuntu-latest<br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; &#8211; name: Setup Kubectl<br>&nbsp; &nbsp; &nbsp; &nbsp; uses: azure\/setup-kubectl@v1<br>&nbsp; &nbsp; &nbsp; &#8211; name: Apply Deployment<br>&nbsp; &nbsp; &nbsp; &nbsp; run: kubectl apply -f deployment.yaml<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Complete pipeline example for a web application. This pipeline covers the following stages:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Checkout the code.<\/li>\n\n\n\n<li>Set up dependencies (Node.js, Python, etc., based on the web app&#8217;s tech stack).<\/li>\n\n\n\n<li>Run tests.<\/li>\n\n\n\n<li>Build the web app.<\/li>\n\n\n\n<li>Deploy the web app.<\/li>\n\n\n\n<li>Notify on success or failure.<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>name: Web App CI\/CD Pipeline<br><br># This pipeline is triggered by a push to the main branch or any feature branches<br>on:<br>&nbsp; push:<br>&nbsp; &nbsp; branches:<br>&nbsp; &nbsp; &nbsp; &#8211; main &nbsp; &nbsp; &nbsp; &nbsp; # Trigger on push to the main branch<br>&nbsp; &nbsp; &nbsp; &#8211; &#8216;feature\/*&#8217;&nbsp; # Trigger on push to any feature branch<br>&nbsp; pull_request:<br>&nbsp; &nbsp; branches:<br>&nbsp; &nbsp; &nbsp; &#8211; main &nbsp; &nbsp; &nbsp; &nbsp; # Trigger for pull requests to the main branch<br><br>jobs:<br>&nbsp; # Job 1: CI &#8211; Continuous Integration (Build &amp; Test)<br>&nbsp; ci:<br>&nbsp; &nbsp; runs-on: ubuntu-latest<br><br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; # Step 1: Checkout the repository code<br>&nbsp; &nbsp; &nbsp; &#8211; name: Checkout repository<br>&nbsp; &nbsp; &nbsp; &nbsp; uses: actions\/checkout@v2<br>&nbsp; &nbsp; &nbsp; &nbsp; # This checks out the code so that the next steps can use it<br><br>&nbsp; &nbsp; &nbsp; # Step 2: Set up Node.js environment<br>&nbsp; &nbsp; &nbsp; &#8211; name: Set up Node.js (for Node.js-based web apps)<br>&nbsp; &nbsp; &nbsp; &nbsp; uses: actions\/setup-node@v2<br>&nbsp; &nbsp; &nbsp; &nbsp; with:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; node-version: &#8217;16&#8217;&nbsp; # Set the desired Node.js version<br><br>&nbsp; &nbsp; &nbsp; # Step 3: Install dependencies<br>&nbsp; &nbsp; &nbsp; &#8211; name: Install dependencies<br>&nbsp; &nbsp; &nbsp; &nbsp; run: |<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; npm install&nbsp; # Install dependencies from package.json (or use yarn)<br><br>&nbsp; &nbsp; &nbsp; # Step 4: Run tests<br>&nbsp; &nbsp; &nbsp; &#8211; name: Run tests<br>&nbsp; &nbsp; &nbsp; &nbsp; run: |<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; npm test&nbsp; # Run your test suite (adjust if you&#8217;re using a different testing framework)<br><br>&nbsp; # Job 2: Build &#8211; Build the web app<br>&nbsp; build:<br>&nbsp; &nbsp; runs-on: ubuntu-latest<br>&nbsp; &nbsp; needs: ci&nbsp; # This job depends on the ci job; it will run after successful tests<br><br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; # Step 1: Checkout the repository (same as in the previous job)<br>&nbsp; &nbsp; &nbsp; &#8211; name: Checkout repository<br>&nbsp; &nbsp; &nbsp; &nbsp; uses: actions\/checkout@v2<br><br>&nbsp; &nbsp; &nbsp; # Step 2: Set up Node.js again (required for build)<br>&nbsp; &nbsp; &nbsp; &#8211; name: Set up Node.js<br>&nbsp; &nbsp; &nbsp; &nbsp; uses: actions\/setup-node@v2<br>&nbsp; &nbsp; &nbsp; &nbsp; with:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; node-version: &#8217;16&#8217;&nbsp; # Make sure to use the same Node.js version<br><br>&nbsp; &nbsp; &nbsp; # Step 3: Install dependencies (again, in case some are needed for the build)<br>&nbsp; &nbsp; &nbsp; &#8211; name: Install dependencies<br>&nbsp; &nbsp; &nbsp; &nbsp; run: |<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; npm install<br><br>&nbsp; &nbsp; &nbsp; # Step 4: Build the application<br>&nbsp; &nbsp; &nbsp; &#8211; name: Build the web app<br>&nbsp; &nbsp; &nbsp; &nbsp; run: |<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; npm run build&nbsp; # Adjust this to your build command (e.g., webpack, create-react-app, etc.)<br><br>&nbsp; # Job 3: Deploy &#8211; Deploy the web app to a server (e.g., AWS, DigitalOcean, etc.)<br>&nbsp; deploy:<br>&nbsp; &nbsp; runs-on: ubuntu-latest<br>&nbsp; &nbsp; needs: build&nbsp; # This job depends on the build job; it will run after a successful build<br><br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; # Step 1: Checkout the repository<br>&nbsp; &nbsp; &nbsp; &#8211; name: Checkout repository<br>&nbsp; &nbsp; &nbsp; &nbsp; uses: actions\/checkout@v2<br><br>&nbsp; &nbsp; &nbsp; # Step 2: Set up environment variables (optional)<br>&nbsp; &nbsp; &nbsp; &#8211; name: Set up deployment secrets<br>&nbsp; &nbsp; &nbsp; &nbsp; run: echo &#8220;DEPLOY_KEY=${{ secrets.DEPLOY_KEY }}&#8221; &gt;&gt; $GITHUB_ENV&nbsp; # Example for a deploy key (add your secret to GitHub Actions secrets)<br><br>&nbsp; &nbsp; &nbsp; # Step 3: Deploy to server (adjust to your deployment method)<br>&nbsp; &nbsp; &nbsp; &#8211; name: Deploy to server<br>&nbsp; &nbsp; &nbsp; &nbsp; run: |<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Example: Using SSH to deploy via SCP or rsync<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ssh -i ${{ secrets.DEPLOY_KEY }} user@server.com &#8216;cd \/path\/to\/your\/web\/app &amp;&amp; git pull &amp;&amp; npm install &amp;&amp; pm2 restart app&#8217;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Or use any other deployment tool (e.g., FTP, SFTP, AWS CLI, etc.)<br><br>&nbsp; # Job 4: Notify &#8211; Send notifications after the pipeline runs (success or failure)<br>&nbsp; notify:<br>&nbsp; &nbsp; runs-on: ubuntu-latest<br>&nbsp; &nbsp; needs: deploy&nbsp; # This job depends on the deploy job<br><br>&nbsp; &nbsp; steps:<br>&nbsp; &nbsp; &nbsp; # Step 1: Send success or failure notification<br>&nbsp; &nbsp; &nbsp; &#8211; name: Send notification on success\/failure<br>&nbsp; &nbsp; &nbsp; &nbsp; run: |<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Check if the workflow was successful or failed<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if [[ $GITHUB_RUN_STATUS == &#8220;success&#8221; ]]; then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Send success notification (e.g., to Slack)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; curl -X POST -H &#8216;Content-type: application\/json&#8217; \\<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8211;data &#8216;{&#8220;text&#8221;:&#8221;Build and deployment successful!&#8221;}&#8217; \\<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; https:\/\/hooks.slack.com\/services\/YOUR\/SLACK\/WEBHOOK<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Send failure notification (e.g., to Slack)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; curl -X POST -H &#8216;Content-type: application\/json&#8217; \\<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8211;data &#8216;{&#8220;text&#8221;:&#8221;Build or deployment failed. Please check the logs!&#8221;}&#8217; \\<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; https:\/\/hooks.slack.com\/services\/YOUR\/SLACK\/WEBHOOK<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>4. Conclusion<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This guide provides a structured approach to learning GitHub Actions from basic syntax to advanced use cases. By following these steps, you can create robust CI\/CD pipelines using GitHub-hosted and self-hosted runners.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For more details, refer to the<a href=\"https:\/\/docs.github.com\/en\/actions\"> GitHub Actions Documentation<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. Introduction to GitHub Actions What is GitHub Actions? GitHub Actions is a CI\/CD (Continuous Integration and Continuous Deployment) tool that allows developers to automate workflows directly in their GitHub repository. It helps automate software development processes like testing, building, and deploying applications. Why Use GitHub Actions? Use Cases Hosted Runners vs. Self-Hosted Runners Hosted [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4102,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,94],"tags":[48,52,51,590,591,592],"class_list":["post-4101","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cicd","category-github-action-cicd","tag-cicd","tag-continuous-deployment","tag-continuous-integration","tag-github-action","tag-github-workflow","tag-github-cicd"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>GitHub Actions: Complete Step-by-Step Guide - code2deploy.com<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"GitHub Actions: Complete Step-by-Step Guide - code2deploy.com\" \/>\n<meta property=\"og:description\" content=\"1. Introduction to GitHub Actions What is GitHub Actions? GitHub Actions is a CI\/CD (Continuous Integration and Continuous Deployment) tool that allows developers to automate workflows directly in their GitHub repository. It helps automate software development processes like testing, building, and deploying applications. Why Use GitHub Actions? Use Cases Hosted Runners vs. Self-Hosted Runners Hosted [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/\" \/>\n<meta property=\"og:site_name\" content=\"code2deploy.com\" \/>\n<meta property=\"article:published_time\" content=\"2025-03-08T18:03:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/code2deploy.com\/blog\/wp-content\/uploads\/2025\/03\/github-actions.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1192\" \/>\n\t<meta property=\"og:image:height\" content=\"633\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"enam\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"enam\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/\"},\"author\":{\"name\":\"enam\",\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/#\\\/schema\\\/person\\\/e46930c19b999a87f12566fa8357481b\"},\"headline\":\"GitHub Actions: Complete Step-by-Step Guide\",\"datePublished\":\"2025-03-08T18:03:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/\"},\"wordCount\":3208,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/#\\\/schema\\\/person\\\/e46930c19b999a87f12566fa8357481b\"},\"image\":{\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/03\\\/github-actions.png\",\"keywords\":[\"CICD\",\"Continuous Deployment\",\"Continuous Integration\",\"Github Action\",\"Github Workflow\",\"GitHub-CICD\"],\"articleSection\":[\"CICD\",\"Github-Action\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/\",\"url\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/\",\"name\":\"GitHub Actions: Complete Step-by-Step Guide - code2deploy.com\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/03\\\/github-actions.png\",\"datePublished\":\"2025-03-08T18:03:18+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/#primaryimage\",\"url\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/03\\\/github-actions.png\",\"contentUrl\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/03\\\/github-actions.png\",\"width\":1192,\"height\":633,\"caption\":\"github-actions\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/github-actions-complete-step-by-step-guide\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"GitHub Actions: Complete Step-by-Step Guide\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/\",\"name\":\"code2deploy.com\\\/blog\",\"description\":\"TechOps\",\"publisher\":{\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/#\\\/schema\\\/person\\\/e46930c19b999a87f12566fa8357481b\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/#\\\/schema\\\/person\\\/e46930c19b999a87f12566fa8357481b\",\"name\":\"enam\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d864e2f082f4499f8f1b33f004ec166eea77b9e94738553b120b6dca2410f203?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d864e2f082f4499f8f1b33f004ec166eea77b9e94738553b120b6dca2410f203?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d864e2f082f4499f8f1b33f004ec166eea77b9e94738553b120b6dca2410f203?s=96&d=mm&r=g\",\"caption\":\"enam\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d864e2f082f4499f8f1b33f004ec166eea77b9e94738553b120b6dca2410f203?s=96&d=mm&r=g\"},\"sameAs\":[\"https:\\\/\\\/code2deploy.com\\\/blog\"],\"url\":\"https:\\\/\\\/code2deploy.com\\\/blog\\\/author\\\/enam\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"GitHub Actions: Complete Step-by-Step Guide - code2deploy.com","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/","og_locale":"en_US","og_type":"article","og_title":"GitHub Actions: Complete Step-by-Step Guide - code2deploy.com","og_description":"1. Introduction to GitHub Actions What is GitHub Actions? GitHub Actions is a CI\/CD (Continuous Integration and Continuous Deployment) tool that allows developers to automate workflows directly in their GitHub repository. It helps automate software development processes like testing, building, and deploying applications. Why Use GitHub Actions? Use Cases Hosted Runners vs. Self-Hosted Runners Hosted [&hellip;]","og_url":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/","og_site_name":"code2deploy.com","article_published_time":"2025-03-08T18:03:18+00:00","og_image":[{"width":1192,"height":633,"url":"https:\/\/code2deploy.com\/blog\/wp-content\/uploads\/2025\/03\/github-actions.png","type":"image\/png"}],"author":"enam","twitter_card":"summary_large_image","twitter_misc":{"Written by":"enam","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/#article","isPartOf":{"@id":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/"},"author":{"name":"enam","@id":"https:\/\/code2deploy.com\/blog\/#\/schema\/person\/e46930c19b999a87f12566fa8357481b"},"headline":"GitHub Actions: Complete Step-by-Step Guide","datePublished":"2025-03-08T18:03:18+00:00","mainEntityOfPage":{"@id":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/"},"wordCount":3208,"commentCount":0,"publisher":{"@id":"https:\/\/code2deploy.com\/blog\/#\/schema\/person\/e46930c19b999a87f12566fa8357481b"},"image":{"@id":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/#primaryimage"},"thumbnailUrl":"https:\/\/code2deploy.com\/blog\/wp-content\/uploads\/2025\/03\/github-actions.png","keywords":["CICD","Continuous Deployment","Continuous Integration","Github Action","Github Workflow","GitHub-CICD"],"articleSection":["CICD","Github-Action"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/","url":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/","name":"GitHub Actions: Complete Step-by-Step Guide - code2deploy.com","isPartOf":{"@id":"https:\/\/code2deploy.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/#primaryimage"},"image":{"@id":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/#primaryimage"},"thumbnailUrl":"https:\/\/code2deploy.com\/blog\/wp-content\/uploads\/2025\/03\/github-actions.png","datePublished":"2025-03-08T18:03:18+00:00","breadcrumb":{"@id":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/#primaryimage","url":"https:\/\/code2deploy.com\/blog\/wp-content\/uploads\/2025\/03\/github-actions.png","contentUrl":"https:\/\/code2deploy.com\/blog\/wp-content\/uploads\/2025\/03\/github-actions.png","width":1192,"height":633,"caption":"github-actions"},{"@type":"BreadcrumbList","@id":"https:\/\/code2deploy.com\/blog\/github-actions-complete-step-by-step-guide\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/code2deploy.com\/blog\/"},{"@type":"ListItem","position":2,"name":"GitHub Actions: Complete Step-by-Step Guide"}]},{"@type":"WebSite","@id":"https:\/\/code2deploy.com\/blog\/#website","url":"https:\/\/code2deploy.com\/blog\/","name":"code2deploy.com\/blog","description":"TechOps","publisher":{"@id":"https:\/\/code2deploy.com\/blog\/#\/schema\/person\/e46930c19b999a87f12566fa8357481b"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/code2deploy.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/code2deploy.com\/blog\/#\/schema\/person\/e46930c19b999a87f12566fa8357481b","name":"enam","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/d864e2f082f4499f8f1b33f004ec166eea77b9e94738553b120b6dca2410f203?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/d864e2f082f4499f8f1b33f004ec166eea77b9e94738553b120b6dca2410f203?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d864e2f082f4499f8f1b33f004ec166eea77b9e94738553b120b6dca2410f203?s=96&d=mm&r=g","caption":"enam"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/d864e2f082f4499f8f1b33f004ec166eea77b9e94738553b120b6dca2410f203?s=96&d=mm&r=g"},"sameAs":["https:\/\/code2deploy.com\/blog"],"url":"https:\/\/code2deploy.com\/blog\/author\/enam\/"}]}},"_links":{"self":[{"href":"https:\/\/code2deploy.com\/blog\/wp-json\/wp\/v2\/posts\/4101","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code2deploy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code2deploy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code2deploy.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/code2deploy.com\/blog\/wp-json\/wp\/v2\/comments?post=4101"}],"version-history":[{"count":2,"href":"https:\/\/code2deploy.com\/blog\/wp-json\/wp\/v2\/posts\/4101\/revisions"}],"predecessor-version":[{"id":4104,"href":"https:\/\/code2deploy.com\/blog\/wp-json\/wp\/v2\/posts\/4101\/revisions\/4104"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/code2deploy.com\/blog\/wp-json\/wp\/v2\/media\/4102"}],"wp:attachment":[{"href":"https:\/\/code2deploy.com\/blog\/wp-json\/wp\/v2\/media?parent=4101"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code2deploy.com\/blog\/wp-json\/wp\/v2\/categories?post=4101"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code2deploy.com\/blog\/wp-json\/wp\/v2\/tags?post=4101"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}