Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ Flags:
--skip-full-sync This must be set to skip a full sync ($BATON_SKIP_FULL_SYNC)
--ticketing This must be set to enable ticketing support ($BATON_TICKETING)
--token string required: The GitHub access token used to connect to the GitHub API. ($BATON_TOKEN)
--sync-last-activity See when members were last active in your organizations, based on audit-log activity. ($BATON_SYNC_LAST_ACTIVITY)
--sync-secrets Whether to sync secrets or not ($BATON_SYNC_SECRETS)
-v, --version version for baton-github-enterprise

Expand Down
12 changes: 10 additions & 2 deletions config_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@
"displayName": "Optimize sync for large organizations",
"description": "Reduces API calls by using grant expansion for team-based repo access and skipping per-team detail fetches. Recommended for large orgs.",
"boolField": {}
},
{
"name": "sync-last-activity",
"displayName": "Sync user last activity",
"description": "See when members were last active in your organizations, based on audit-log activity.",
"boolField": {}
}
],
"displayName": "GitHub Enterprise",
Expand All @@ -199,7 +205,8 @@
"orgs",
"enterprises",
"omit-archived-repositories",
"direct-collaborators-only"
"direct-collaborators-only",
"sync-last-activity"
],
"default": true
},
Expand All @@ -215,7 +222,8 @@
"enterprises",
"sync-secrets",
"omit-archived-repositories",
"direct-collaborators-only"
"direct-collaborators-only",
"sync-last-activity"
]
}
]
Expand Down
33 changes: 32 additions & 1 deletion docs/connector.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@ If you access GitHub at `github.com`, go to the [GitHub](/baton/github) integrat
| Licenses | <Icon icon="square-check" iconType="solid" color="#c937ae"/> | |
| Secrets - API keys | <Icon icon="square-check" iconType="solid" color="#c937ae"/> | |
| GitHub App | <Icon icon="square-check" iconType="solid" color="#c937ae"/> | |
| GitHub Activity\*\*\* | <Icon icon="square-check" iconType="solid" color="#c937ae"/> | |

The GitHub Enterprise connector supports [automatic account provisioning and deprovisioning](/product/admin/account-provisioning). New accounts will send an invitation to the account owner; if an invitation is pending, the account status will be shown as **Unspecified**.
The GitHub Enterprise connector supports [automatic account provisioning and deprovisioning](/product/admin/account-provisioning). New accounts will send an invitation to the account owner; if an invitation is pending, the account status will be shown as **Pending**.

\* Due to limitations on the GitHub API, syncing multiple orgs requires a personal access token (PAT). A separate connector and GitHub app is required when using the GitHub App integration.

\*\* Organization roles are also referred to as "enterprise licenses" in GitHub's documentation.

\*\*\* Only synced when **Sync user last activity** is enabled. See [Sync member last activity](#sync-member-last-activity) below.

[This connector can sync secrets](/product/admin/inventory) and display them on the **Inventory** page.

<Warning>
Expand Down Expand Up @@ -243,6 +246,8 @@ If you're using a personal access token to set up the connector:
1. **Optional.** If you do not want to include archived repos in syncs, click to enable **Omit archived repositories**.

1. **Optional.** For large organizations, click to enable **Optimize sync for large organizations**. This reduces API calls by using grant expansion for team-based repo access and skipping per-team detail fetches.

1. **Optional.** If you want to see when members were last active, click to enable **Sync user last activity**. See [Sync member last activity](#sync-member-last-activity) for requirements and limitations.
</Step>
<Step>
If you're using a GitHub app to set up the connector:
Expand All @@ -262,6 +267,8 @@ If you're using a GitHub app to set up the connector:
1. **Optional.** If you do not want to include archived repos in syncs, click to enable **Omit archived repositories**.

1. **Optional.** For large organizations, click to enable **Optimize sync for large organizations**. This reduces API calls by using grant expansion for team-based repo access and skipping per-team detail fetches.

1. **Optional.** If you want to see when members were last active, click to enable **Sync user last activity**. See [Sync member last activity](#sync-member-last-activity) for requirements and limitations.
</Step>
<Step>
Click **Save**.
Expand Down Expand Up @@ -320,6 +327,7 @@ baton-github-enterprise
| `BATON_DIRECT_COLLABORATORS_ONLY` | Set to `true` to optimize sync for large organizations by reducing API calls (uses grant expansion for team-based repo access and skips per-team detail fetches). |
| `BATON_PROVISIONING` | Set to `true` to enable provisioning and deprovisioning. |
| `BATON_SYNC_SECRETS` | Set to `true` to sync secrets (API keys). |
| `BATON_SYNC_LAST_ACTIVITY` | Set to `true` to see when members were last active. See [Sync member last activity](#sync-member-last-activity) for requirements and limitations. |
</Step>
<Step>
The connector connects to your C1 tenant and begins syncing. Verify it appears as **Connected** in **Apps** > **Connectors**.
Expand Down Expand Up @@ -356,6 +364,7 @@ baton-github-enterprise \
| `--enterprises` | Comma-separated list of enterprises to sync enterprise roles for. |
| `--omit-archived-repositories` | Exclude archived repositories from syncs. |
| `--direct-collaborators-only` | Optimize sync for large organizations by reducing API calls (uses grant expansion for team-based repo access and skips per-team detail fetches). |
| `--sync-last-activity` | See when members were last active. See [Sync member last activity](#sync-member-last-activity) for requirements and limitations. |
| `--provisioning` | Enable provisioning and deprovisioning. |
</Step>
<Step>
Expand All @@ -382,6 +391,28 @@ When deploying on Kubernetes with a minimal base image (for example, Debian slim
</Tab>
</Tabs>

## Sync member last activity

You can enable **Sync user last activity** to have C1 show, for each member, the most recent recorded action across all synced organizations (for example, commenting on an issue or pull request, reviewing code, or changing a setting). This appears on the member's profile in C1 alongside their other access details.

**Requirements:**

- **Personal access token:** the token must have the **read:audit_log** scope, and permission to view each organization's audit log (typically an organization owner).
- **GitHub App:** the app must have the **Organization permissions > Administration: Read-only access** permission. If you followed the GitHub App setup instructions above, this is already granted (it's also required for SAML/SSO detection), so no extra permission needs to be added.

<Warning>
**Enabling the config option alone is not enough.** After you enable **Sync user last activity** (or set `--sync-last-activity` / `BATON_SYNC_LAST_ACTIVITY=true`) and save the connector, go to the connector's **Capabilities & configuration** page in C1 and confirm the **GitHub Activity** resource type is enabled for sync — it will show up in the resource list as available, but disabled, until you manually enable it.

</Warning>

**What "last activity" means:** This is not necessarily a login timestamp. GitHub's audit log only records actions members take, not every time someone signs in or browses the product. Because of this, C1 shows the most recent recorded action for a member, whatever that action was, as a best-effort signal of when they were last active. A member who only reads or browses without taking any recorded action won't show a last-activity date, even if they use GitHub regularly.

To keep this fast on large organizations, raw Git operations (pushes, fetches, and clones done via `git` rather than the website or API) are not counted toward last activity — only web and API actions are. A member who exclusively interacts with GitHub through `git` and never uses the website or API (for example, a purely command-line workflow with no PR reviews, comments, or settings changes) won't show a last-activity date, even though they're actively using GitHub.

If a member has never taken a recorded action, or if the connector can't reach an organization's audit log for any reason (for example, a missing scope or a plan without audit log access), C1 simply won't show a last-activity date for that member — this does not affect the rest of the sync.

Activity is delivered as an ongoing background feed rather than as part of each full sync, so it may take a little time after enabling this option before last-activity dates first appear, and dates update continuously afterward rather than only at sync time.

## Troubleshooting

### "Resource not accessible by integration" error
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/conductorone/baton-github-enterprise
go 1.25.2

require (
github.com/conductorone/baton-github v0.4.0
github.com/conductorone/baton-github v0.4.7
github.com/conductorone/baton-sdk v0.30.1
github.com/ennyjfrick/ruleguard-logfatal v0.0.2
github.com/quasilyte/go-ruleguard/dsl v0.3.23
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ github.com/cockroachdb/swiss v0.0.0-20260820225851-333444432258 h1:IJ+uNItEm0qx9
github.com/cockroachdb/swiss v0.0.0-20260820225851-333444432258/go.mod h1:yBRu/cnL4ks9bgy4vAASdjIW+/xMlFwuHKqtmh3GZQg=
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo=
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ=
github.com/conductorone/baton-github v0.4.0 h1:Hf72uDLoYrtmhII6BYyRs0qSG/vuhx6Po7QHHs4618E=
github.com/conductorone/baton-github v0.4.0/go.mod h1:SUpbLLRnO+fldsV/ALUd6JjONtUcsPya38psMNBIDCU=
github.com/conductorone/baton-github v0.4.7 h1:a/YRA4Iy4ey9wk2Azrg0v+E/AWmltnvPzVkPGJIQP6c=
github.com/conductorone/baton-github v0.4.7/go.mod h1:rooHPNjHMlUi/5WTG7obpFwwLEqJQr9CCyLzgF2IGus=
github.com/conductorone/baton-sdk v0.30.1 h1:NfDk6KCrOhQUMOGU8ZAgHK898rE2h8wvDEt1fXylr0M=
github.com/conductorone/baton-sdk v0.30.1/go.mod h1:9iFpBag59RlwGkb4Tz6omYewqnj8obfbZzrtSaTLa5Q=
github.com/conductorone/dpop v0.3.0 h1:j5fZk0VqepGKYo+/NDikCOMsZcgs4HO4i0k56wRel5g=
Expand Down
1 change: 1 addition & 0 deletions pkg/config/conf.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 13 additions & 3 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ var (
"and skipping per-team detail fetches. Recommended for large orgs.",
),
)

syncLastActivity = field.BoolField(
"sync-last-activity",
Comment thread
JavierCarnelli-ConductorOne marked this conversation as resolved.
field.WithDisplayName("Sync user last activity"),
field.WithDescription("See when members were last active in your organizations, based on audit-log activity."),
)
)

//go:generate go run ./gen
Expand All @@ -90,6 +96,7 @@ var Config = field.NewConfiguration(
syncSecrets,
omitArchivedRepositories,
directCollaboratorsOnly,
syncLastActivity,
},
field.WithConnectorDisplayName("GitHub Enterprise"),
field.WithHelpUrl("/docs/baton/github-enterprise"),
Expand All @@ -99,15 +106,18 @@ var Config = field.NewConfiguration(
Name: GithubPersonalAccessTokenGroup,
DisplayName: "Personal access token",
HelpText: "Use a personal access token for authentication.",
Fields: []field.SchemaField{instanceUrlField, accessTokenField, orgsField, EnterprisesField, omitArchivedRepositories, directCollaboratorsOnly},
Fields: []field.SchemaField{instanceUrlField, accessTokenField, orgsField, EnterprisesField, omitArchivedRepositories, directCollaboratorsOnly, syncLastActivity},
Default: true,
},
{
Name: GithubAppGroup,
DisplayName: "GitHub app",
HelpText: "Use a github app for authentication",
Fields: []field.SchemaField{instanceUrlField, appIDField, appPrivateKeyPath, orgField, EnterprisesField, syncSecrets, omitArchivedRepositories, directCollaboratorsOnly},
Default: false,
Fields: []field.SchemaField{
instanceUrlField, appIDField, appPrivateKeyPath, orgField, EnterprisesField,
syncSecrets, omitArchivedRepositories, directCollaboratorsOnly, syncLastActivity,
},
Default: false,
},
}),
)
1 change: 1 addition & 0 deletions pkg/connector/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func NewLambdaConnector(ctx context.Context, ghc *cfg.Githubenterprise, cliOpts
AppPrivatekeyPath: ghc.AppPrivatekeyPath,
Org: ghc.Org,
DirectCollaboratorsOnly: ghc.DirectCollaboratorsOnly,
SyncLastActivity: ghc.SyncLastActivity,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: DefaultCapabilitiesBuilder (lines 45-58) deliberately enumerates every conditionally-registered builder (APITokenBuilder, EnterpriseRoleBuilder, LicenseBuilder) so the config-less capabilities output advertises them all, but the new usage-app / "GitHub Activity" syncer is not listed and this type does not implement EventFeeds. Since builder.GetCapabilities derives resource types from ResourceSyncers() and CAPABILITY_EVENT_FEED_V2 from EventFeeds(), the default capabilities will omit both — which contradicts docs/connector.mdx:401 ("on a brand-new connector, this resource type is included by default"). Note newUsageAppBuilder/newUsageEventFeed are unexported in baton-github v0.4.5, so this likely needs an upstream export before it can be wired here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Known, already discussed on baton-github#188: DefaultCapabilitiesBuilder only feeds the offline capabilities CLI/catalog artifact (pre-install marketplace listing), not the live per-instance capability check that actually gates real syncs — that one calls GetMetadata() against the real running connector, which already implements EventFeeds()/usage-app correctly. So this has no effect on whether the feature works for a configured connector; it's a cosmetic gap in the pre-install catalog listing only. Deliberately not fixing it here — it'd require exporting currently-private constructors from baton-github for a purely cosmetic win.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not about this line specifically, but while you're in here: v0.4.5 also adds AppPrivatekey (raw PEM) upstream, and appPrivateKeyPEM() prefers it over the path. Githubenterprise never got the field, so it's always empty for this connector.

Not a regression — app-privatekey-path is still WithRequired(true) so the fallback always hits — just means GitHub App users here can't use the paste-the-PEM option that baton-github has. Intentional?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed on the SU today, we will skip these and enable them only if requested

}, cliOpts)
}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 32 additions & 3 deletions vendor/github.com/conductorone/baton-github/pkg/config/config.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading