Analytics
Check out all of our GitHub Actions: https://actions.cicirello.org/
GitHub Actions | |
---|---|
Build Status | |
Source Info | |
Support |
The cicirello/count-action-users GitHub Action generates a Shields endpoint with the count of the number of workflows that use a GitHub Action. It is thus a tool for maintainers of GitHub Actions, and it can be used to insert a badge with a users count into the README for a GitHub Action. The key features include:
count-action-users
action accepts a list of GitHub Actions as an input, generating endpoints for all actions
in the list. In this way, a single run of the action in a single workflow in a single repository
is sufficient to regularly monitor the number of users of all of the actions that you maintain.
Or, if you prefer, you can run the action separately within the repositories of each action.The developers of the count-action-users
GitHub Action are not affiliated
with the developers of Shields, although like most of GitHub we use their badges
in most of our repositories.
Here are a Few Example Badges
actions/setup-python
:
actions/checkout
:
The remainder of the documentation is organized as follows:
This first workflow runs on a schedule (daily at 4am), and it can also
be run manually if need be (via the workflow_dispatch
event). It uses all
of the default action inputs. The default location for the generated endpoint
is the root of the repository. In this example, there is a single action that
we are monitoring: owner/action-name
. The action names the endpoint file using
the name of the action, so in this case, the name of the file it creates is:
action-name.json
. Please note that the GITHUB_TOKEN
must be passed as an
environment variable, as shown in the workflow, to authenticate to the GitHub API.
name: count-action-users
on:
schedule:
- cron: '0 4 * * *'
workflow_dispatch:
jobs:
count:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Generate user count JSON endpoint
uses: cicirello/count-action-users@v1
with:
action-list: owner/action-name
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
You can then pass the URL of the endpoint to Shields to generate and
insert a badge into your README with the following Markdown. Just be sure to
replace OWNERUSERID
, REPOSITORY
, and BRANCH
as appropriate.
![Count of Action Users](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/OWNERUSERID/REPOSITORY/BRANCH/action-name.json)
Note that in the above, you are relying on GitHub's raw.githubusercontent.com
server for serving the endpoint to Shields. We do not actually recommend doing this
as that server isn't really intended for that purpose, and may create a delay
that will trickle down to Shields serving the badge. However, you might initially
set it up this way to try out the action.
See Example 2
and Example 3
for examples of our recommended approach, serving via GitHub Pages.
See later in this document for an example of the markdown needed to link the badge to a GitHub search results page with the workflows represented by the user count.
If you maintain more than one GitHub Action and want to generate user count endpoints for all of them with a single application of this action, then you can pass a list of your GitHub actions as follows:
name: count-action-users
on:
schedule:
- cron: '0 4 * * *'
workflow_dispatch:
jobs:
count:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Generate user count JSON endpoint
uses: cicirello/count-action-users@v1
with:
action-list: >
owner/action-one
owner/action-two
owner/action-three
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
The above example will generate the following JSON files:
action-one.json
, action-two.json
, and action-three.json
.
Note that the >
is one of the ways to specify a multiline string
in YAML.
The previous example relies on GitHub's raw.githubusercontent.com
server for serving the endpoint to Shields. This is less than ideal
as that server is intended for those browsing GitHub to see the
raw version of files, and isn't really intended for general serving
of files.
GitHub Pages (our recommended approach): We instead recommend utilizing
GitHub Pages. The benefit of this is that you will gain the advantage of the
CDN that backs GitHub Pages, thus significantly
enhancing the speed of serving the endpoint to Shields.
First note that you do not necessarily need to setup a full
website for this purpose. You can literally use it to serve nothing but
your user count JSON endpoint, if you don't want to otherwise set up a full project
page. Follow GitHub's directions for enabling GitHub Pages
on the repository in which you want to use the count-action-users
action.
To do this, go to the settings tab of that repository, and then select "Pages" in the
left. In this example, we are assuming serving from the "docs" directory of your
default branch, so make those selections as you enable "Pages" for your repository.
Once you do, anything you store in the "docs" directory will be served
from the URL: https://YOURUSERID.github.io/REPOSITORY/
.
So, now run the action using this workflow:
name: count-action-users
on:
schedule:
- cron: '0 4 * * *'
workflow_dispatch:
jobs:
count:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Generate user count JSON endpoint
uses: cicirello/count-action-users@v1
with:
target-directory: docs
action-list: owner/action-name
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
Note that the above workflow uses the
target-directory
input to store the endpoint in the docs directory,
which will be created by the action if it doesn't already exist.
Assuming that you have configured GitHub Pages to serve from "docs",
then your endpoint will be accessible from
https://YOURUSERID.github.io/REPOSITORY/action-name.json
.
You can then use the following Markdown to insert the badge in your README.
Just be sure to replace YOURUSERID
and REPOSITORY
as appropriate.
![Count of Action Users](https://img.shields.io/endpoint?url=https://YOURUSERID.github.io/REPOSITORY/action-name.json)
If you are also utilizing GitHub Pages for a project site, then you might want
to store the endpoint in a subdirectory of "docs" to keep your site's files organized.
For example, perhaps you want to store it in a directory "endpoints", then you can
accomplish that with the following action input: target-directory: docs/endpoints
.
This would change the necessary Markdown for inserting the badge to:
![Count of Action Users](https://img.shields.io/endpoint?url=https://YOURUSERID.github.io/REPOSITORY/endpoints/action-name.json)
See later in this document for an example of the markdown needed to link the badge to a GitHub search results page with the workflows represented by the user count.
GitHub Pages allows you to serve your site from either the "docs" directory
(as in the above example), or from the root of any branch. Assuming you are
setting this up in the repository of the action that you maintain, then the
default branch is not a good choice for your project site. Instead, create
a gh-pages
branch in your repository (you can then delete everything in the
gh-pages
branch, as it only needs to contain the source of your project site).
Just like Example 2 above, you don't really need to have a project site, as your
site can literally be just the endpoint you want to pass to Shields.
Now, setup the following workflow in the default branch (e.g., "main")
of your repository. Note that even though this workflow will be pushing to the gh-pages
branch,
the workflow itself must be in the default branch, or else the schedule will not run.
name: count-action-users
on:
schedule:
- cron: '0 4 * * *'
workflow_dispatch:
jobs:
count:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: gh-pages
- name: Generate user count JSON endpoint
uses: cicirello/count-action-users@v1
with:
action-list: owner/action-name
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
You'll notice above that the count-action-users
step
did not change. Instead, the checkout
step changed to
checkout the gh-pages
branch of the repository. The
count-action-users
action commits and pushes to the
checked out branch.
As in the previous example, the JSON endpoint will be at
the root of the project site
(https://YOURUSERID.github.io/REPOSITORY/action-name.json
). Thus, you can then use the
following Markdown to insert the badge in your README.
Just be sure to replace YOURUSERID
and REPOSITORY
as appropriate.
![Count of Action Users](https://img.shields.io/endpoint?url=https://YOURUSERID.github.io/REPOSITORY/action-name.json)
If you'd rather have it in a subdirectory, you can set the appropriate action input,
such as with: target-directory: endpoints
. Doing so would then require
the following Markdown for inserting the badge into the README:
![Count of Action Users](https://img.shields.io/endpoint?url=https://YOURUSERID.github.io/REPOSITORY/endpoints/action-name.json)
See later in this document for an example of the markdown needed to link the badge to a GitHub search results page with the workflows represented by the user count.
The default permissions of the GITHUB_TOKEN
are sufficient for pushing
to a protected branch, provided that the branch protection hasn't been
configured with required reviews nor with required checks. If the repository where
you are running the count-action-users
action does have a branch protection
rule with required reviews or required checks, there are a couple solutions.
Not Recommended: First, you could create a personal access token (PAT) with necessary permissions, save it as a repository secret, and use the PAT with during the actions/checkout step (see actions/checkout's documentation). However, we do not recommend doing so. If anyone else has write access to the repository, then they can potentially create additional workflows using that PAT to bypass the required checks and/or reviews; and you obviously had a reason for putting those requirements in place.
Recommended: Although your default branch likely has branch protection rules
that include required checks and/or reviews, you do not need to store your
user count endpoint in the default branch.
See Example 3
earlier, which uses the gh-pages
branch along with GitHub Pages to serve the
endpoint to Shields. You can configure branch protection on the gh-pages
branch, and as long as you don't add any required checks or reviews for that
specific branch, the action will be able to push to it without the need for a PAT.
All of the above examples used the major release tag
for the count-action-users
step
(i.e., uses: cicirello/count-action-users@v1
):
- name: Generate user count JSON endpoint
uses: cicirello/count-action-users@v1
with:
action-list: owner/action-name
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
The advantage to this is that you will automatically get all non-breaking changes and bug fixes without the need to alter your workflow. If you prefer to use a specific release, just use the SemVer of the release that you wish to use, such as with the following:
- name: Generate user count JSON endpoint
uses: cicirello/count-action-users@v1.0.2
with:
action-list: owner/action-name
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
If you do use a specific release, then we recommend configuring GitHub's Dependabot in your repository. Dependabot can be used to monitor dependencies, including GitHub Actions, and generates automated pull requests to update versions. The PRs it generates includes the text of release notes and ChangeLogs giving you the opportunity to decide whether to upgrade the version.
It is common practice to link status badges to something relevant (e.g., a build status badge to workflow runs). For a users count badge, you might consider linking it to a GitHub search results page. You can do that with the following Markdown. Replace "YOURUSERID" with the user id of the owner of the action, and replace "ACTIONNAME" with the name of the action. Also replace "RELEVANT_SHIELDS_URL" with the link that generates the badge from the endpoint (see the examples in the workflow examples above).
[![Count of Action Users](RELEVANT_SHIELDS_URL)](https://github.com/search?q=YOURUSERID+ACTIONNAME+path:.github/workflows+language:YAML&type=Code)
Why not instead submit a pull request to Shields to add direct support to their awesome project for an actions users count badge? The GitHub Code Search API, which we utilize for this action, has a rate limit of 30 queries per minute for an authenticated user; and can also potentially interact with other secondary rate limits, including some secondary limits that are not published. By running this as an action, the necessary queries benefit from the GITHUB_TOKEN of the user of this action, and in theory we can more easily stay within the rate limits. I imagine the rate limit would be significantly more challenging for a solution directly integrated with Shields. We additionally have a built-in time delay in between queries for those using the action to monitor multiple GitHub actions.
How does count-action-users
work? The count-action-users
action queries GitHub's
Code Search API. The search is restricted to the contents of files in the .github/workflows
directory (since active workflows must be in that directory to run) and restricted to
the YAML language (the language for workflows). The search terms then include
the owner of the action and the name of the action. It is possible that some false positives
may be included in the count. For example, although GitHub requires actions in the marketplace to
have unique names, if an action has a simple enough name, that name may be found within that
of another action with a longer name. Including the owner name in the search should
minimize false positives. See the documentation of
GitHub's code search
for details of what code is (and is not) indexed by GitHub.
Can't we further minimize false positives with "owner/action-name" as a single search
term? Unfortunately, GitHub's code search drops various special characters that are often
used as wildcards from searches, including /
, replacing them with
spaces. Due to this, combining owner and the
action's name into a single search
term in this way is equivalent to the search we are currently doing.
Most of the inputs have default values that should be sufficient in most
cases. Only the action-list
input is required.
action-list
(REQUIRED)This input is required. All other inputs are optional. This input is a comma or space separated list of the GitHub Actions for which you want user count endpoints generated. We recommend that you include both owner name and action name, rather than just the action name, to improve accuracy of results. For example, if I was running this for this very action, I would set this input as follows:
- name: Generate user count JSON endpoint
uses: cicirello/count-action-users@v1
with:
action-list: cicirello/count-action-users
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
The action will also work if you only use the action name (e.g., action-list: count-action-users
),
but the results may be less accurate. Although GitHub requires each action to have a
unique name, if the name of your action is relatively simple, then there may be other
action names that include your action's name within. By including the owner name
of the action in the search, you can minimize some false positives in the results.
If you maintain several GitHub Actions, then we recommend that you utilize a YAML multiline string when specifying this input to make your workflow easy to read. For example:
- name: Generate user count JSON endpoint
uses: cicirello/count-action-users@v1
with:
action-list: >
owner/action-one
owner/action-two
owner/action-three
owner/action-four
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
The >
in the above is one of YAML's ways of specifying a multiline string.
The action also doesn't care who the owners of the actions are, and will work if
different actions have different owners, such as with the following:
- name: Generate user count JSON endpoint
uses: cicirello/count-action-users@v1
with:
action-list: >
owner/action-one
anotherOwner/action-two
somebodyElse/action-three
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
The filename of each endpoint is of the form: action-name.json
.
target-directory
This is the directory, relative to the root of the repository in which the action is run, where the JSON endpoints will be stored. It defaults to the root of the repository. If the target directory doesn't exist, then the action will create it.
color
This is the color for the right side of the badge (the side with the count
of action users). The default is the shade of blue that is currently
used by Shields to designate that the badge is "informational". You can pass 3-digit hex
(e.g., color: '#333'
), 6-digit hex (e.g., color: '#343434'
), or named
colors (e.g., blue
). Anything that is valid in CSS, SVG, etc is valid
for this input. However, the action does not do any validation of the color that
you pass. Note that the quotes are required if you use hex because the #
is
a special character to YAML.
include-logo
This input controls whether or not a logo is inserted in the badge. The default is
true
.
named-logo
This controls which logo is inserted if a logo is included in the badge. The default is
githubactions
, which is the GitHub Actions logo. Another to consider
is github
, which is the GitHub logo. You can pass the name of any logo supported
by Shields, which also includes
simple-icons.
style
This controls the style of the badge, and can be any style that is supported by
Shields. The default is flat
, which happens to
also be the Shields default.
fail-on-error
This input enables you to control what happens if the action fails for some reason (e.g., error communicating with the GitHub's Code Search API, etc).
The default is fail-on-error: true
, which means that if
an error occurs it will cause the workflow to fail. The rationale
for this default is that the failed workflow will lead to a
GitHub notification so that you know something went wrong.
If you'd rather just let it quietly fail, to most likely correct
itself during the next run, then pass fail-on-error: false
(actually anything other than true
will be treated as false
).
commit-and-push
The commit-and-push
input controls whether the action commits
and pushes the generated JSON endpoints upon creation. It defaults to
commit-and-push: true
. If the user count changed since
last commit, then as long as you are not running this in a detached
head state (such as on a pull request event), the action will commit
and push the new endpoint. If you are in a detached head
state, such as if you were to run this during a pull request
(not sure why you would), then the action will simply and quietly
skip the commit/push without issuing an error.
If your branch is protected with either required reviews or required
checks, then the push will fail with an error. Whether this also
fails your workflow depends on how you have set
the fail-on-error
input. See the earlier discussion for what you
can do if you wish to use the action in a repository
that has required reviews or required checks:
Protected branches with required checks.
The author of the commit is set to the github-actions bot.
query-delay
This input specifies a delay, in seconds, in between queries for cases where multiple actions are being monitored. The purpose of this delay is to decrease chance of hitting API rate limits. The default is 65 seconds, which ensures that no more than one code search query is executed per minute. This input doesn't accept values less than 33. For example, if you attempt to pass 0 (or anything else less than 33), the minimum of 33 will be used instead. That minimum ensures that at most two code search queries will be executed per minute.
Why is the default, and minimum, query delays so high? Although the rate limit is 30 code search queries per minute, there are other unpublished secondary rate limits. During our initial testing, we occasionally ran into such secondary limits when using a lower query delay that allowed for four queries in a minute, specifically on the fourth query. It is unclear what other activity was interacting to hit those secondary rate limits. The default, and minimum, query delays are designed to help you avoid rate limit effects.
Additionally, there is no reason for the action to collect usage statistics of the actions that you maintain more than once per day, so the length of the delay between queries shouldn't really matter much to you. The one case where it might is if you have reason to run this in a private repository, and thus the delay time will count against your actions minutes. In that case you can simply setup one workflow per action that you maintain (thus no delay will be inserted), and make sure you schedule them so that they are far enough apart in time.
The action has only the following action output variable.
exit-code
If the input fail-on-error
is set to false
, then in addition to
quietly failing (i.e., not failing the workflow run), the output exit-code
will be set to a non-zero exit code that may be useful in debugging the
issue. If the input fail-on-error
is set to true
(the default), your
workflow run won't have the opportunity to check the exit-code
output.
However, the exit-code
and a descriptive error message will still be
logged in the workflow output. In either case, if you believe that the
failure is a bug, please include this in any bug reports.
The workflow here shows all possible inputs, with their default
values, and also shows how to access the action's exit-code
output if desired.
name: count-action-users
on:
schedule:
- cron: '0 4 * * *'
workflow_dispatch:
jobs:
count:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Generate user count JSON endpoint
id: endpointStep # Only needed if you want to check the exit-code
uses: cicirello/count-action-users@v1
with:
action-list: owner/action # This input is REQUIRED.
target-directory: '' # Default is root of repository.
color: '#007ec6' # The shade of blue used by Shields for informational badges
include-logo: true
named-logo: githubactions # Defaults to the GitHub Actions logo
style: flat # Which is Shields's default as well
fail-on-error: true
commit-and-push: true
query-delay: 65
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Check exit code if desired
run: |
# Note that if you set fail-on-error to true, you'll
# never actually get here if an error occurs. But if you
# set fail-on-error to false, then instead of failing the
# workflow, the action will output the exit code that would
# have failed the workflow and you can check it here.
echo "exitCode = ${{ steps.endpointStep.outputs.exit-code }}"
The count-action-users
action uses the following:
You can support the project in a number of ways:
count-action-users
action useful, consider starring the
repository.This GitHub Action is licensed under the MIT License.