Centralized GitHub Actions for repository maintenance and automation across the organization.
To install a centralized GitHub Actions (GHA) to a project repo, follow these steps:
-
Configure the GitHub Apps
- The workflows use centrally-maintained GitHub Apps for authorization and authentication. The GitHub Apps must be configured to allow repository access on a project-by-project basis. Access must be granted before running the workflow; however once done, projects do not need to create or maintain tokens or secrets.
- Make sure that the project name ( e.g.
org/project-repo) is selected on the two organizational GitHub Apps:- hfla-workflow-rollout: Gives "Automate the ORG" (source) access to the project (destination) repo during installation.
- hfla-graphql-app: Gives the project (destination) repo access to scripts in "Automate the ORG" (source) during the workflow's runtime.
- For both, first scroll to "Repository access", then "Only select repositories", then select the corresponding project repo in the "Select repositories" dropdown.
- Click "Save".
-
Run the "Rollout Workflow to Project" workflow from "Automate the ORG"
- From the "Automate the ORG" repo, select "Actions", then "Rollout Workflow to Project" on the left.
- On the right, click on "Run workflow" to bring up installation options.
- Confirm that the
mainbranch is selected. - Enter the
org/project-repofor the "Destination repo". - Do not change the "Source repo".
- Select which GitHub Action you would like installed.
- Do not change the "Branch name" or "GitHub App" name.
- OPTIONAL: Dry-run preview mode
a.Only if you would like to review whether the workflow will generate the expected values, check the box for "Dry-run mode" and click "Run workflow".
b. When the workflow completes, error-free runs will be shown with green checks and failures with red x's. If the workflow fails and you cannot determine the cause, contact the ATO team. c. Upon successful completion, click on the most recent "Rollout Workflow to Project" then on the next screen click on "Rollout-Workflow". Scroll down and open "Preview PR body" for the dry-run report to see if this is what you expect.
d. Next, click on "Label-Suggestions/Rollout-Label-Directory", then scroll down to "Preview PR comment". This will show the text for the supplemental comment on the PR. - Rollout the workflow a. Make sure that "Dry-run mode" is not checked, then click "Run workflow". b. The automation will generate the installation PR in the destination repo. c. Go to the Destination repo to review the generated PR.
workflow-configs/
│
├── gha-add-update-label-weekly/ # "Add Update Label Weekly" workflow
│ ├── dist/
│ │ └── index.js # Esbuild's generated build artifact / production entry point
│ ├── action.yml
│ └── index.js
│
├── core/ # Core business logic
│ └── add-update-label-weekly.js # "Add Update Label Weekly" files
│
├── shared/ # Shared utilities across all actions
│ ├── find-linked-issue.js # Find linked issues
│ ├── format-log-messages.js # `logger` utility to sort log messages
│ ├── get-repo-labels.js # Retrieves repo labels
│ ├── hide-issue-comment.js # Minimizes comments
│ ├── manage-issue-labels.js # Set of issue-labelling utilities
│ ├── manage-issue-timeline.js # Set of issue-timeline utilities
│ ├── post-issue-comment.js # Post comment on issue
│ ├── query-issue-info.js # Get issue data (GraphQL)
│ └── resolve-configs.js # Resolve config files
│
├── example-configs/ # Example configuration files
│ ├── add-update-instructions-template.example.md⎫
│ ├── add-update-label-weekly-config.example.yml ⎬ Configs for "Add Update Label Weekly"
│ └── add-update-label-weekly.example.yml ⎭
│
├── .gitignore
├── auto-release.sh # Script for updating version on a branch
├── auto-update-main.sh # Script for updating version on the main
├── package.json
├── package-lock.json
├── CHANGELOG.md # Change log for tracking changes per version
└── README.md # This fileMonitors “In Progress” issues for updates since the last run and posts reminders to assignees who haven’t provided activity.
Full details →
Choose your desired workflow, then follow the steps to implement it in your repo.
- Scans all open, assigned issues with a status of "In progress (actively working)"1.
- Checks for recent comments from the issue assignee since the last automation run2.
- If there are no recent comments from the assignee, posts a reminder3 that the assignee should:
- provide a brief update on their progress,
- describe blockers and request help if needed,
- indicate their availability for working on the issue, and
- share an estimated time to complete the issue.
- Applies the label "statusInactive1" :
status: to update!4 if this is the first notice. - Applies the label "statusInactive2":
status: 2 weeks inactive4 if this is the second notice. - Additional features:
- Minimizes previous, repetitive bot comments within a specified timeframe2.
- Applies the label (default) "statusUpdated":
status: updated4 if an update was posted recently. - Removes previously applied labels when appropriate.
- Ensures ongoing communication, accountability, and support across active tasks.
These are configurable to match your repo, see Step 2: Customize Config →:
1 Project Board status-columns
2 All time thresholds used by the automation
3 Reminder message
4 All label names
Located in shared/, these are used across multiple actions:
Generic configuration loader used by all actions. Handles:
- Loading YAML/JSON config files from project repos
- Merging defaults, file config, and overrides
- Deep merging of nested objects
- Config validation
Each action creates its own config loader in core/[action-name]/config.js that:
- Defines action-specific defaults
- Transforms flat action inputs to nested config structure
- Calls the generic
resolve-configs.js - Validates required fields for that action
Example pattern for new actions:
// core/your-action/config.js
const resolveConfigs = require('../../shared/resolve-configs');
function loadYourActionConfig({ projectRepoPath, configPath, overrides }) {
const defaults = {
// Action-specific defaults
};
const nestedOverrides = {
// Transform flat overrides to nested
};
const config = resolveConfigs({
projectRepoPath,
configPath,
overrides: nestedOverrides,
defaults,
});
// Validate required fields
resolveConfigs.validateConfig(config, ['field1', 'nested.field2']);
return config;
}- Parses PR body to find linked issues, e.g. "Fixes: #123", "Resolves: #456", etc.
- Wraps log messages with tags via
logger.including[STEP],[INFO],[SUCCESS],[WARN],[ERROR],[DEBUG].
- Retrieves list of all labels from repo
- Minimizes comments using GraphQL mutation.
- Collection of utility functions for issue labeling, including
addLabels()anddeleteLabels().
- Collection of utility functions for issue timelines, including
setLocalTime()andgetIssueTimeline().
- Posts a comment onto an issue.
- Uses GraphQL API to find an issue's node_id, Project Board status name, and the corresponding status id.
The following applies to the maintenance of the hackforla/automate-the-org repo only.
git clone https://hackforla/my_github_username/hackforla/automate-the-org.git
cd automate-the-org
npm installSince this is a composite action that runs in the GitHub Actions environment, dependencies are installed automatically in package.json.
Test actions in a separate test repository before releasing next version.
- Create new folder:
new-action-name/ - Add
action.ymlandindex.js - Add logic to
core/if substantial - Add shared utilities to
shared/if reusable - Create example config in
example-configs/ - Update this README
Make all necessary changes and commit as usual:
git add .
git commit -m "what is being committed"
git pushNote: as always, use git add . or git add <individual file> as appropriate
Rebuild the esbuild files, then re-commit:
npm install
npm run build
git add .
git commit -m "new release build"
git pushUpdate the CHANGELOG.md with the latest changes (using prefixes such as "fix: " or "feat: " -see CHANGELOG.md) as needed, then double-check the most recent version:
git tagThis should match the most recent version listed in the CHANGELOG.md, which should also match the latest version listed in package.json. If it doesn't, then you may need to manually correct the versions.
Now run the automatic versioning utilities. These will check whether you have set an upstream, and ask whether the next version should be a patch, minor, or major version change per semver (e.g. version MAJOR.MINOR.PATCH):
./auto-release.shOnce the final commit is made to the main branch at Automate-the-ORG:
./auto-update-main.shUse the following for adjustments to the version tags (but only if you understand what you are doing!)
- To remove previously-committed versions:
Remember to adjust
git tag -d <version> git push origin --delete <version>
CHANGELOG.mdandpackage.jsonalso. - If you did not set your upstream branch but pushed the version anyway, you will need to set your
upstreamtomainbranch, then:git push upstream <version>
- Create a feature branch
- Make your changes
- Test in a test repository
- Submit a pull request
- After approval, tag a new release
- Issues: Open an issue in this repository
- Questions: Contact DevOps team
- Docs: See action-specific documentation above
MIT