<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Github-Actions on Douglas Domingos :: CompSci@UFCG</title><link>https://dougdomingos.netlify.app/tags/github-actions/</link><description>Recent content in Github-Actions on Douglas Domingos :: CompSci@UFCG</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Fri, 01 Nov 2024 17:35:48 -0300</lastBuildDate><atom:link href="https://dougdomingos.netlify.app/tags/github-actions/index.xml" rel="self" type="application/rss+xml"/><item><title>Automating tasks with Github Actions</title><link>https://dougdomingos.netlify.app/posts/automating-tasks-with-github-actions/</link><pubDate>Fri, 01 Nov 2024 17:35:48 -0300</pubDate><guid>https://dougdomingos.netlify.app/posts/automating-tasks-with-github-actions/</guid><description>Introduction In software development, it’s common to have some tasks that need to be executed regularly, at a specific time or in a certain order. Usually, teams would write dedicated scripts for these tasks, which adds complexity and diverts focus from the main product.
That&amp;rsquo;s where CI/CD platforms comes in, streamlining development workflows by automating repetitive tasks so developers can focus on the actual software. Here, we’ll be exploring one of these platforms: GitHub Actions.</description><content>&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>In software development, it’s common to have some tasks that need to be executed
regularly, at a specific time or in a certain order. Usually, teams would write
dedicated scripts for these tasks, which &lt;strong>adds complexity and diverts focus&lt;/strong>
from the main product.&lt;/p>
&lt;p>That&amp;rsquo;s where &lt;strong>CI/CD platforms&lt;/strong> comes in, streamlining development workflows by
automating repetitive tasks so developers can focus on the actual software.
Here, we’ll be exploring one of these platforms: &lt;strong>GitHub Actions&lt;/strong>.&lt;/p>
&lt;h2 id="what-are-github-actions">What are GitHub Actions?&lt;/h2>
&lt;p>&lt;strong>GitHub Actions&lt;/strong> is a &lt;strong>CI/CD platform integrated directly into GitHub&lt;/strong>,
which allows you to easily automate tasks within repositories. &lt;strong>Each repository
can have multiple workflows&lt;/strong>, represented by YAML files located in the
&lt;code>.github/workflows/&lt;/code> directory. As you&amp;rsquo;ll see, this makes workflows &lt;strong>easy to
write and understand&lt;/strong>.&lt;/p>
&lt;p>You can define &lt;strong>workflows triggered by various events&lt;/strong>, such as pushes and
pull requests, and use them for a wide range of tasks — testing, deploying to
production, enforcing code style, and much more. Workflows can even be
&lt;strong>scheduled&lt;/strong>, &lt;strong>combined with other workflows&lt;/strong>, and used to &lt;strong>update your
repositories&lt;/strong>. Plus, &lt;strong>you can leverage actions created by other developers&lt;/strong>!&lt;/p>
&lt;h2 id="setting-up-an-workflow">Setting up an workflow&lt;/h2>
&lt;p>New workflows can be added to your repository in two ways:&lt;/p>
&lt;ul>
&lt;li>Through &lt;a href="https://github.com/">GitHub&lt;/a>, where you can choose from many template
workflows and adjust them as needed&lt;/li>
&lt;li>&lt;strong>By manually creating the workflow file&lt;/strong> inside &lt;code>.github/workflows&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>Regardless of your choice, describing workflows is writing YAML files. And, to
fully understand the structure of a workflow, let&amp;rsquo;s create one that simply
prints &amp;ldquo;Hello Actions!&amp;rdquo; at each push made to the repository.&lt;/p>
&lt;h2 id="workflow-structure">Workflow structure&lt;/h2>
&lt;p>Implementing our &amp;ldquo;Hello Actions&amp;rdquo; workflow is as simple as this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Simple Action&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">on&lt;/span>: &lt;span style="color:#ae81ff">push&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">jobs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">print-msg&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">runs-on&lt;/span>: &lt;span style="color:#ae81ff">ubuntu-latest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">steps&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Print message&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">run&lt;/span>: &lt;span style="color:#ae81ff">echo &amp;#34;Hello Actions!&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now, let&amp;rsquo;s understand what each part of this code does:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;code>name&lt;/code>, as it suggests, defines the name of the workflow. While it is
optional, &lt;strong>I strongly recommend&lt;/strong> to always specify the workflow name — not
only for readability, but also to &lt;strong>allow workflow composition&lt;/strong>.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>on&lt;/code> defines the &lt;strong>events that will trigger the workflow&amp;rsquo;s execution&lt;/strong>. You
can specify &lt;strong>multiple triggers&lt;/strong> for the same workflow, and even &lt;strong>restrict
the event scope&lt;/strong> (e.g. pull requests to a specific branch, or changes made to
a specific file).&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>jobs&lt;/code> describe &lt;strong>the actions performed by the workflow&lt;/strong>. An workflow can
have multiple jobs (that are executed on parallel by default), where each job
is &lt;strong>identified by an unique name&lt;/strong>.&lt;/p>
&lt;ul>
&lt;li>Each job must define &lt;strong>the environment it runs on&lt;/strong> (which is specified by
the &lt;code>runs-on&lt;/code> key)&lt;/li>
&lt;li>A job describes &lt;strong>the tasks it executes as a sequence of &lt;code>steps&lt;/code>&lt;/strong>. Each
step can execute commands, setup tasks and even other actions&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="example-1-automating-tests-for-pull-requests-made-to-the-main-branch">Example 1: Automating tests for pull requests made to the &lt;code>main&lt;/code> branch&lt;/h2>
&lt;p>&lt;strong>Automating tests plays a crucial role at code maintainabilty&lt;/strong>, as it ensures
that &lt;strong>changes made to the codebase do not break what previously worked&lt;/strong>. Such
task can be easily achieved with GitHub Actions by setting up &lt;strong>an workflow that
is executed for every pull request&lt;/strong> made to the repository.&lt;/p>
&lt;p>Consider a project written in Java with Maven as build tool. We want to
&lt;strong>automatically run all test classes&lt;/strong> for every pull request made to the &lt;code>main&lt;/code>
branch. This can be achieved with the following workflow:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Run tests with Maven&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># The workflow only runs for pull requests made to the &amp;#34;main&amp;#34; branch&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">on&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">pull_requests&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">branches&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;main&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">jobs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">run-tests&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">runs-on&lt;/span>: &lt;span style="color:#ae81ff">ubuntu-latest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">steps&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Checks out (e.g. clones) the repository into the Actions runner&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">uses&lt;/span>: &lt;span style="color:#ae81ff">actions/checkout@v4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Install the required Java version&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Set up Java 17&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">uses&lt;/span>: &lt;span style="color:#ae81ff">actions/setup-java@v4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">with&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">java-version&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;17&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">distribution&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;temurin&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">cache&lt;/span>: &lt;span style="color:#ae81ff">maven&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Run tests with Maven&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Test with Maven&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">run&lt;/span>: &lt;span style="color:#ae81ff">mvn test&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="example-2-scheduled-updates-of-a-repository">Example 2: Scheduled updates of a repository&lt;/h2>
&lt;p>In my &lt;a href="https://github.com/dougdomingos/portfolio-v1">old website&lt;/a>, I&amp;rsquo;ve set up
Next.js to regularly fetch my repository list from
&lt;a href="https://api.github.com">GitHub API&lt;/a>, so that my project list would always be
updated. After migrating to &lt;a href="https://gohugo.io/">Hugo&lt;/a>, I kept wondering on how
to implement this functionality with as little overhead as possible.&lt;/p>
&lt;p>It turns out that &lt;strong>GitHub Actions was perfect for my scenario&lt;/strong>. Simply write a
workflow that &lt;strong>fetches data from GitHub API&lt;/strong> and &lt;strong>commits the updated list
into the repository&lt;/strong>. After some &lt;em>googling&lt;/em> (and a little help from ChatGPT), I
was able to come up with an working solution.&lt;/p>
&lt;p>While &lt;strong>I chose to use Python for the fetch script&lt;/strong>, you could write a similar
solution in plain old Shell Script (though the equivalent code would likely be
&lt;em>much&lt;/em> more verbose) or in any language you prefer.&lt;/p>
&lt;p>First, here&amp;rsquo;s my Python script for fetching and parsing the data, at
&lt;code>.github/scripts/fetch_data.py&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> requests
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">import&lt;/span> yaml
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">fetch_github_repos&lt;/span>(username: str):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&amp;#34;Fetch the repositories of a user from GitHub API
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> Args:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> username (str): The username of the account to be fetched
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> The contents of the response as a JSON object
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> FETCH_URL &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;https://api.github.com/users/&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>username&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/repos&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> response &lt;span style="color:#f92672">=&lt;/span> requests&lt;span style="color:#f92672">.&lt;/span>get(FETCH_URL)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> response&lt;span style="color:#f92672">.&lt;/span>status_code &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#ae81ff">200&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> print(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Failed while fetching data: HTTP &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>response&lt;span style="color:#f92672">.&lt;/span>status_code&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> response&lt;span style="color:#f92672">.&lt;/span>json()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">convert_to_yaml&lt;/span>(repo_list: list):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;&amp;#34;&amp;#34;Given the contents of the request, create the equivalent YAML file.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> Args:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> repos_data (list): The JSON structure of repository
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Order repositories by most recent updated&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> repo_list &lt;span style="color:#f92672">=&lt;/span> sorted(repo_list, key&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">lambda&lt;/span> repo: repo[&lt;span style="color:#e6db74">&amp;#34;updated_at&amp;#34;&lt;/span>], reverse&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">True&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> projects &lt;span style="color:#f92672">=&lt;/span> []
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">for&lt;/span> repo &lt;span style="color:#f92672">in&lt;/span> repo_list:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># You can add more properties here&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> project &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;link&amp;#34;&lt;/span>: repo[&lt;span style="color:#e6db74">&amp;#34;html_url&amp;#34;&lt;/span>],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;info&amp;#34;&lt;/span>: {&lt;span style="color:#e6db74">&amp;#34;title&amp;#34;&lt;/span>: repo[&lt;span style="color:#e6db74">&amp;#34;name&amp;#34;&lt;/span>], &lt;span style="color:#e6db74">&amp;#34;description&amp;#34;&lt;/span>: repo[&lt;span style="color:#e6db74">&amp;#34;description&amp;#34;&lt;/span>]},
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">&amp;#34;tags&amp;#34;&lt;/span>: repo[&lt;span style="color:#e6db74">&amp;#34;topics&amp;#34;&lt;/span>],
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> projects&lt;span style="color:#f92672">.&lt;/span>append(project)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> data &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#e6db74">&amp;#34;projects&amp;#34;&lt;/span>: projects}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Saves the project list as a YAML file&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">with&lt;/span> open(&lt;span style="color:#e6db74">&amp;#34;./data/projects.yaml&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;w&amp;#34;&lt;/span>) &lt;span style="color:#66d9ef">as&lt;/span> outfile:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> yaml&lt;span style="color:#f92672">.&lt;/span>dump(data, outfile, default_flow_style&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">False&lt;/span>, sort_keys&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">False&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> __name__ &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;__main__&amp;#34;&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> convert_to_yaml(fetch_github_repos(&lt;span style="color:#e6db74">&amp;#34;your_username&amp;#34;&lt;/span>))
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>As for the workflow file, at &lt;code>.github/workflows/fetch_projects.yaml&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Update project list&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Actions allow you to define environment variables too!&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">env&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">SCRIPT_PATH&lt;/span>: &lt;span style="color:#ae81ff">.github/scripts/fetch_projects.py&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Gives the workflow write permissions over the repository&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">permissions&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">contents&lt;/span>: &lt;span style="color:#ae81ff">write&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Workflow is scheduled to run every Sunday at 00h00&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">on&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">schedule&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">cron&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;0 0 * * 0&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">workflow_dispatch&lt;/span>: &lt;span style="color:#75715e"># this allows us to manually run the workflow in GitHub&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">jobs&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">update-list&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">runs-on&lt;/span>: &lt;span style="color:#ae81ff">ubuntu-latest&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">steps&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Checkout&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">uses&lt;/span>: &lt;span style="color:#ae81ff">actions/checkout@v4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Set up Python&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">uses&lt;/span>: &lt;span style="color:#ae81ff">actions/setup-python@v5&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">with&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">python-version&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;3.10&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Install dependencies&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">run&lt;/span>: &lt;span style="color:#ae81ff">pip install pyyaml requests&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Run script&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">run&lt;/span>: &lt;span style="color:#ae81ff">python ${{ env.SCRIPT_PATH }}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#f92672">name&lt;/span>: &lt;span style="color:#ae81ff">Commit changes to repository&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">run&lt;/span>: |&lt;span style="color:#e6db74">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> git config --global user.name &amp;#34;&amp;lt;your-username-here&amp;gt;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> git config --global user.email &amp;#34;&amp;lt;your-email-here&amp;gt;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> git add ./data/projects.yaml
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> git commit -m &amp;#34;chore(actions): update project list&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> git push&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>&lt;strong>Cron syntax&lt;/strong>: Cron schedules are specified by strings composed of five
fields in a &lt;code>M H DM MN DW&lt;/code> format, as described below:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>M H DM MN DW
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>| | | | |
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>| | | | └── Day of the week (0-7, where 0 and 7 = Sunday)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>| | | └───── Month (1-12)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>| | └──────── Day of the month (1-31)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>| └─────────── Hour (0-23)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>└────────────── Minute (0-59)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>So, &lt;code>0 0 * * 0&lt;/code> means &amp;ldquo;at 00h00 of any day of any month on Sunday&amp;rdquo;&lt;/p>
&lt;/blockquote>
&lt;p>Also, to ensure that the updated list is avaliable in the website after the
script is executed, I&amp;rsquo;ve added a &amp;ldquo;hook&amp;rdquo; to &lt;strong>trigger the &lt;code>build&lt;/code> workflow every
time the &lt;code>Update project list&lt;/code> workflow is executed&lt;/strong> — thus the importance of
&lt;strong>always naming your workflows&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># ...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">on&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># ...&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># Specifies that the &amp;#34;build&amp;#34; workflow should execute after the&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e"># &amp;#34;Update project list&amp;#34; workflow is completed&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">workflow_run&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">workflows&lt;/span>: [&lt;span style="color:#e6db74">&amp;#34;Update project list&amp;#34;&lt;/span>]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">types&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> - &lt;span style="color:#ae81ff">completed&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># ...&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="conclusion">Conclusion&lt;/h2>
&lt;p>GitHub Actions, as well as other CI/CD platforms, are &lt;strong>a powerful tool to
master&lt;/strong>. While I do believe this post may help you with the basics, &lt;strong>I
recommend taking a deeper look into the
&lt;a href="https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions">GitHub Actions documentation&lt;/a>&lt;/strong>.&lt;/p>
&lt;p>Also, feel free to use any of the workflows you&amp;rsquo;ve seen here in your projects.
Try adding some new features, or combining them with your own.&lt;/p>
&lt;p>That&amp;rsquo;s it for now. See ya! &amp;#x1f44b;&lt;/p></content></item></channel></rss>