GitHub Actions and Workflows: A Beginner’s Guide

GitHub Actions is a feature of GitHub that allows users to automate tasks directly on GitHub. It provides a way for users to easily create custom automated workflows or “Actions” that can be triggered by various events such as pushing code to the repository, creating or editing an issue, or manually triggering the workflow. These workflows can be used to build, test, package, release, and deploy applications and software, as well as automate other types of tasks.

Here, we’ll introduce GitHub Actions and workflows. You’ll learn the types of actions you can use and where to find them. You’ll also look at examples of these types of actions and how they fit in a workflow.

What is GitHub Actions?

GitHub Actions are packaged scripts to automate tasks in a software development workflow in GitHub. You can configure GitHub Actions to trigger complex workflows that meet your organization’s needs; each time developers check new source code into a specific branch, at timed intervals, or manually. The result is a reliable and sustainable automated workflow, which leads to a significant decrease in development time.

 

GitHub decreases time from idea to deployment

GitHub is designed to help teams of developers and DevOps engineers build and deploy applications quickly. There are many features in GitHub that enable this, but they generally fall into one of two categories:

  • Communication: Consider all of the ways that GitHub makes it easy for a team of developers to communicate about the software development project: code reviews in pull requests, GitHub issues, project boards, wikis, notifications, and so on.
  • Automation: GitHub Actions lets your team automate workflows at every step in the software-development process, from integration to delivery to deployment. It even lets you automate adding labels to pull requests and checking for stale issues and pull requests.

When combined, these features have allowed thousands of development teams to effectively decrease the amount of time it takes from their initial idea to deployment.

Use workflow automation to decrease development time

In this module we’ll focus on automation, so let’s take a moment to understand how teams can use automation to reduce the amount of time it takes to complete a typical development and deployment workflow.

Consider all of the tasks that must happen after the code is written, but before the code can be reliably used for its intended purpose. Depending on your organization’s goals, you’ll likely need to perform one or more of the following tasks:

  • Ensure the code passes all unit tests
  • Perform code quality and compliance checks to make sure the source code meets the organization’s standards
  • Check the code and its dependencies for known security issues
  • Build the code integrating new source from (potentially) multiple contributors
  • Ensure the software passes integration tests
  • Version the new build
  • Deliver the new binaries to the appropriate filesystem location
  • Deploy the new binaries to one or more servers
  • If any of these tasks do not pass, report the issue to the proper individual or team for resolution

The challenge is to do these tasks reliably, consistently, and in a sustainable manner. This is an ideal job for workflow automation. If you’re already relying on GitHub, you’ll likely want to set up your workflow automation using GitHub Actions.

Where can you find GitHub Actions?

GitHub Actions are scripts that adhere to a yml data format. Each repository has an Actions tab that provides a quick and easy way to get started with setting up your first script. If you see a workflow that you think might be a great starting point, just select the Configure button to add the script and begin editing the source yml.

github-actions--01

 

However, beyond those GitHub Actions featured on the Actions tab, you can:

  • Search for GitHub Actions in the GitHub Marketplace. The GitHub Marketplace allows you to discover and purchase tools that extend your workflow.
  • Search for open-source projects. For example, the GitHub Actions organization features many popular open-source repos containing GitHub Actions you can use.
  • Write your own GitHub Actions from scratch. Furthermore, if you want, you could make them open source, or even publish them to the GitHub Marketplace.

Using open-source GitHub Actions

Many GitHub Actions are open source and available for anyone who wants to use them. However, just like with any open-source software, you need to carefully check them before using them in your project. Similar to recommended community standards with open-source software, such as including a README, code of conduct, contributing file, and issue templates, just to name a few, you can follow the following recommendations when using GitHub Actions:

  • Review the action’s action.yml file for inputs, outputs, and to make sure the code does what it says it does.
  • Check if the action is in the GitHub Marketplace. This is a good check, even if an action does not have to be on the GitHub Marketplace to be valid.
  • Check if the action is verified in the GitHub Marketplace. This means that GitHub has approved the use of this action. However, you should still review it before using it.
  • Include the version of the action you’re using by specifying a Git ref, SHA, or tag.

Two types of GitHub actions

There are two types of GitHub actions: container actions and JavaScript actions.

With container actions, the environment is part of the action’s code. These actions can only be run in a Linux environment that GitHub hosts. Container actions support many different languages.

JavaScript actions don’t include the environment in the code. You’ll have to specify the environment to execute these actions. You can run these actions in a VM in the cloud or on-premises. JavaScript actions support Linux, macOS, and Windows environments.

The anatomy of a GitHub action

Here’s an example of an action that performs a git checkout of a repository. This action, actions/checkout@v1, is part of a step in a workflow. This step also builds the Node.js code that was checked out. We’ll talk about workflows, jobs, and steps in the next section.

steps:
- uses: actions/checkout@v1
- name: npm install and build webpack
run: |
npm install
npm run build

Suppose you want to use a container action to run containerized code. Your action might look like this:

name: "Hello Actions"
description: "Greet someone"
author: "[email protected]"

inputs:
MY_NAME:
description: "Who to greet"
required: true
default: "World"

runs:
uses: "docker"
image: "Dockerfile"

branding:
icon: "mic"
color: "purple"

Notice the inputs section. Here, you’re getting the value of a variable called MY_NAME. This variable will be set in the workflow that runs this action.

In the runs section, notice you specify docker in the uses attribute. When you do this, you’ll need to provide the path to the docker image file. Here, it’s called Dockerfile. We won’t get into the specifics of Docker here, but if you would like more information, check out the Introduction to Docker Containers.

The last section, branding, personalizes your action in the GitHub Marketplace if you decide to publish it there.

You can find a complete list of action metadata at Metadata syntax for GitHub Actions.

What is a GitHub Actions workflow?

GitHub Actions workflow is a process that you set up in your repository to automate software-development lifecycle tasks, including GitHub Actions. With a workflow, you can build, test, package, release, and deploy any project on GitHub.

To create a workflow, you add actions to a .yml file in the .github/workflows directory in your GitHub repository.

In the exercise coming up, your workflow file, main.yml, will look like this.

name: A workflow for my Hello World file
on: push
jobs:
build:
name: Hello world action
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: ./action-a
with:
MY_NAME: "Mona"

 

Notice the on: attribute. This is a trigger to specify when this workflow will run. Here, it triggers a run when there’s a push event to your repository. You can specify single events like on: push, an array of events like on: [push, pull_request], or an event-configuration map that schedules a workflow or restricts the execution of a workflow to specific files, tags, or branch changes. The map might look something like this:

on:
# Trigger the workflow on push or pull request,
# but only for the main branch
push:
branches:
- main
pull_request:
branches:
- main
# Also trigger on page_build, as well as release created events
page_build:
release:
types: # This configuration does not affect the page_build event above
- created

 

An event will trigger on all activity types for the event unless you specify the type or types. For a comprehensive list of events and their activity types, see: Events that trigger workflows in the GitHub documentation.

A workflow must have at least one job. A job is a section of the workflow that will be associated with a runner. A runner can be GitHub-hosted or self-hosted, and the job can run on a machine or in a container. You’ll specify the runner with the runs-on: attribute. Here, you’re telling the workflow to run this job on ubuntu-latest.

Each job will have steps to complete. In our example, the step uses the action actions/checkout@v1 to check out the repository. What’s interesting is the uses: ./action-a value, which is the path to the container action that you build in an action.yml file. We looked at the contents of an action.yml file in the What is GitHub Actions? section.

The last part of this workflow file sets the MY_NAME variable value for this workflow. Recall the container action took an input called MY_NAME.

For more information on workflow syntax, see Workflow syntax for GitHub Actions

GitHub-hosted versus self-hosted runners

We briefly mentioned runners as being associated with a job. A runner is simply a server that has the GitHub Actions runner application installed. In the previous workflow example, there was a runs-on: ubuntu-latest attribute within the jobs block, which told the workflow that the job will run using the GitHub-hosted runner that is running in the environment ubuntu-latest.

When it comes to runners, there are two options to choose from: GitHub-hosted runners or self-hosted runners. If you use a GitHub-hosted runner, each job runs in a fresh instance of a virtual environment that is specified by the GitHub-hosted runner type you define, runs-on: {operating system-version}. With self-hosted runners, you need to apply the self-hosted label, its operating system, and the system architecture. For example, a self-hosted runner with a Linux operating system and ARM32 architecture would look like the following, runs-on: [self-hosted, linux, ARM32].

Each type of runner has its benefits, but GitHub-hosted runners offer a quicker, simpler way to run your workflows, albeit with limited options. Self-hosted runners are a highly configurable way to run workflows in your own custom local environment. Self-hosted runners can be run on-premises or in the cloud. You can also use self-hosted runners to create a custom hardware configuration with more processing power or memory to run larger jobs, install software available on your local network, and choose an operating system not offered by GitHub-hosted runners.

GitHub Actions may have usage limits

GitHub Actions has some usage limits, depending on whether your runner is GitHub-hosted or self-hosted and your GitHub plan. For more information on usage limits, check out Usage limits, billing, and administration in the GitHub documentation.

Don’t forget to tell us about your favorite GitHub features in the comment below.

Read More: DigitalOcean Promo Code 2023: $200 credit for 60 days

What is PowerShell?

powershellPowerShell

Microsoft PowerShell is a free and open source command shell, scripting language, and remote management framework. PowerShell is intended for network administrators, cloud hosting administration, not professional web programmers, and has replaced the old CMD shell and VBScript as the most popular shell and scripting language for Windows. PowerShell is also available for GNU/Linux and Mac OS on GitHub (https://github.com/PowerShell/PowerShell).

Strictly speaking, PowerShell is part of the Windows Management Framework (WMF), so Microsoft and others often refer to “WMF” instead of to “PowerShell”, but this is a branding and marketing mistake, so manual will almost always just refer to PowerShell and rarely to WMF.
Similar to the CMD shell, you can work in PowerShell interactively, manually typing and executing commands as needed while “in” the shell, or it can run uncompiled scripts written in a scripting language specifically for it. PowerShell scripts end with the “psi” filename extension, not “bat” or “cmd”, and are simple text files.

Unlike the CMD shell, however, PowerShell is built on top of the .NET Framework and is itself a compiled .NET program. PowerShell does not pipe text streams, as virtually every other Windows- or UNIX-based shell does, but complete .NET objects, including all of their properties and methods!

These properties and methods are accessible to your PowerShell scripts, and PowerShell was specifically designed around them. This object-orientation in a shell scripting language is sometimes disorienting to administrators with prior shell language experience.

How to Create views and templates in Django

When you’re first beginning to create websites, having static pages seems only natural. But what if you want to get a little creative and have data change per user or per page?

That’s where using templates can ease the process of developing apps. Templates give you the option to use the same page multiple times throughout the site, with sections of data that can continuously change depending on the request.

This tutorial shows you why creating dynamic pages is worth the time. It also shows you how to easily create and manage them.

In this tutorial, you’ll learn how to:

  • Work with views.
  • Use template variables and tags.
  • Add dynamic data to Django templates.
  • Use template inheritance.

In this module, we’ll work on a website for dog shelters. This project focuses on collecting information for all existing dog shelters and the dogs they’re hoping to place across the country. The fictional hope for this app is that dogs will be able to find suitable homes faster because they’ll have individuals looking to adopt them from around the United States and not just their local area.

DjangoFDJ is a good framework for this project because it provides a route for quickly developing a customer-facing app. It also provides an established database and admin function that employees can easily access for quick updating. We’ve created the initial setup for the project, so we can focus on the concepts for this module.

Requirements

To complete the exercises, you’ll need the following items installed on your computer:

Clone the starter repository

  1. Open a command window or terminal.
  2. Run the following commands to clone the starter repository and change to the project’s directory.
git clone https://github.com/MicrosoftDocs/mslearn-django-views-templates
cd mslearn-django-views-templates/starter

 

l

Open the project in Visual Studio Code

We’ll use Visual Studio Code as our code editor.

In the same command or terminal window, enter the following command to open the folder in Visual Studio Code:

code .

Create the virtual environment

We’ll follow the best practice of working with virtual environments for our project.

  1. In Visual Studio Code, open the terminal window by selecting View > terminal.
  2. In the new terminal window, run the following commands to create and activate a virtual environment:
# Windows
py -3 -m venv venv
.\\venv\\Scripts\\activate

# macOS or Linux
python3 -m venv venv
source ./venv/bin/activate

h

Install Django

The starter project uses a requirements.txt file to contain the list of all necessary packages. We can install them by using pip.

In the same terminal window, run the following command to install the required packages:

pip install -r requirements.txt

;

Start the server

Django can host the application locally. We’ll do this by using the built-in terminal window in Visual Studio Code.

Enter the following command in the same terminal window:

python manage.py runserver

\\

;

In programming, a view is typically a component that displays information to the user. The tasks that a view performs can vary depending on the framework and conventions, including responsibility for loading data.

In Django, a view is typically responsible for:

  • Validating a user’s request.
  • Loading or modifying the appropriate data.
  • Returning an HTML template with the information to the user.

We’re going to begin our exploration by discussing creating views manually and configuring the appropriate URLconfs. A URLconf is a list of paths that indicate the pattern to match, the function to call, and optionally a name. In a later unit, we’ll see how Django can automatically handle some of the code that we wrote by hand.

Create a view

To create a view from scratch in Django, you typically create a function. The function commonly contains the appropriate code to:

  • Perform the task that the user has requested.
  • Return a template with the appropriate data to display to the user.

View functions always take at least one parameter named request, which represents the user’s request. You can provide more parameters as needed if you’re expecting more information from the user in the URL, such as the name or ID of an item. You’ll register those when creating the route, which we talk about later in the unit.

Loading data

You can use the Django ORM to load any data that you need from the registered database.

The project that we’re building has two models, Shelter and Dog. We can load all objects or perform other queries by using the models that we created. To load all shelters, for example, we would use Shelter.objects.all(). We can load an individual shelter by using Shelter.objects.get(pk=1).

404 errors

A 404 error in web applications means “not found.” As a best practice, you should return a 404 whenever a request is made for an object that doesn’t exist.

Django provides shortcuts for trying to load data:

  • get_object_or_404 and get_list_or_404: Loads an object by a primary key, or returns a 404 to the user if an object is not found.
  • get_list_or_404: Performs the same operation as the other shortcut, except that it accepts a filter parameter.

We’ll use get_object_or_404 in our exercise.

Rendering the template

Django’s templating engine will take the HTML template that we build, combine it with any data that we provide, and emit the HTML for the browser. The helper function to perform this task is render.

The render function needs the object that represents the request, which is the request parameter that we highlighted earlier. You also pass in the name of the template, typically an HTML file that will reside in a folder named templates.

To pass data into the template, you provide render with a context dictionary object. The context object contains a set of key/value pairs, where each key becomes a variable in the template.

Example

To create a view to display all shelters, you might use the following code:

def shelter_list(request):
    shelters = Shelter.objects.all()
    context = { 'shelters': shelters }
    return render(request, 'shelter_list.html', context)

[

Register a path

Almost any web framework uses paths to process user requests. Paths convert the portion of the URL after the name of the domain and before the query string (which comes after the question mark) into a function call.

A call to www.contoso.com/shelters might call a function to list all shelters, whereas www.contoso.com/shelters/1 might call a function to display a shelter with an ID of 1. You register paths in Django by creating a URLconf.

Let’s say we have a module called views, which is a Django convention. We can route index traffic where a path isn’t specified (such as www.contoso.com) to a function in views called index, and give it a name called index, by using the following path:

path('', views.index, 'index')


We can also create virtual folders for specific requests. For example, if we wanted to list all shelters if someone requests /shelters, we could use the following command:

path('shelters', views.shelter_list, 'shelter_list')

URL parameters

It’s a common practice to pass parameters to an application as part of the URL, such as an ID or a name. Because these values will change, we don’t want to hard code them into our path. In Django, you can specify a parameter by using a special syntax. In that syntax, you can indicate the type of data you’re expecting, such as an integer, and a name.

For example, to create a path for someone to request a specific shelter by an ID, we would want a parameter of type integer. (The reason is that our primary key is an integer.) We can then provide the name that we want to use for the variable, which will then be passed in as a parameter to the view function. The syntax for identifying this parameter would be <int:pk>. Notice the type declaration, the colon, and then the name of the variable.

The full path might look like this:

path('shelter/<int:pk>', views.shelter_detail, name='shelter_detail')

The associated view function would have the following signature:

def shelter_detail(request, pk):
# code

The pk part of the path signature is passed into shelter_detail as a parameter, just as if we were calling it like a normal Python function.

(Continue)