Currently whenever we create a new branch in Maestro we need to manually create a PR in Arcade to add a new YAML file representing that channel. This is a error prone process and create a bunch of duplicated files. The channels' YAML are _very_ similar, therefore we can simplify this process by creating a _Channel Implementation Template_ that could be instantiated whenever a new channel should be created.
/cc @mmitche @riarenas
Here are the goals as I see them:
@JohnTortugo Possibilities to consider:
Another posibility:
We currently specify in the channel templates the feeds that each channel should publish, but this seems like information that would also make sense to keep in BAR about the channel itself.
darc-get-channels --include-feeds (or similar)As an added advantage, we could make it so eventually, darc-add-build-to-channel also publishes the assets to all the feeds it needs to publish to, which will give us channel assignment after the fact without any build or release pipelines running.
Much has changed since we posted the previous messages in this issue. I'll post below some of the major things that changed in the meantime and the current issues we are facing (please complement if I forgot any). In a subsequent message I'll post a proposal to approach the problems.
Recently we added:
Some issues that we currently face:
In the message below I tried to merge the proposals that were posted here and the things that we discussed on Teams.
Create a new task in the Tasks.Feed package that will receive a list of parameters similar to what this task receive. Then it'll proceed to:
This change will require us to modify BAR to add the feeds as an associated entity to the Channel(s).
It will probably be a disruptive change but I think we can do this without requiring any changes on the customers build-definitions, because the changes will be in Arcade post-build scripts.
After this change:
What do you think?
/cc @mmitche @riarenas @markwilkie @chcosta
You mentioned that this will likely be disruptive, in what way are you thinking?
I love the idea of removing the channel definitions from arcade. That would be really fantastic. I do have some questions though:
What if we changed things more radically:
This would also put us in a position to move publishing into a separate pipeline altogether at some point, like @jaredpar wants, but would also be more robust IMO.
The upshot of this would be that you would still be required to check into arcade or another repo to update channel info, but:
Lastly, I think we should move the symbol publishing into the main publishing task, rather than having it be a separate task. Performance is very important here, so if this ends up adversely impacting publishing perf it should remain split out.
You mentioned that this will likely be disruptive, in what way are you thinking?
@markwilkie - Since it's a change in a central part of publishing any error doing it will certainly cause considerably noise. But if we do it carefully nothing should break as there is no change required from the customer side.
- How would we handle addition of new parameters or subtraction of existing ones?
I see that and I was concerned with this too. Please see other comment below.
- Templates point to 'live' master versions of arcade/arcade-publishing (or maybe a tag that we move around based on the arcade-validation results) so that rollout of new publishing infra is just a matter of moving the tag.
You want to introduce this new branch (or repo) so that we can use the templates from that branch as a resource in other pipelines, correct? I imagine that what motivates that is that currently for every channel that we create we need to do changes in the repository. But if that changes become much less often (i.e., not have channels in YAML) then I'm not quite convinced it would justify creating a new repository/branch for this.
I think we need to simplify the overall interface between the components of publishing so that it gets easier to keep this backward compatible or at least easy to migrate to servicing branches. Currently, the publishing flow for a single build is more or less like this:

Perhaps we could simplify it to this:

Which has the following [big] changes:
darc get-build-manifest -format xml -build 123.My thought process here was that simplifying the interface between the Arcade SDK and the post-build stages we can have more confidence that changes that we do in the publishing infra can be back portable. For instance, recently we were 'challenged' because we needed to publish builds produced with Arcade SDK 3.x using the infra that we now have for .Net 5.
This would also put us in a position to move publishing into a separate pipeline altogether...
I think after recent changes we can do that today. Instead of including the post-build.yml stage at the end of his build definition he can do a call to darc add-build-to-channel and it should work the same.
You want to introduce this new branch (or repo) so that we can use the templates from that branch as a resource in other pipelines, correct? I imagine that what motivates that is that currently for every channel that we create we need to do changes in the repository. But if that changes become much less often (i.e., not have channels in YAML) then I'm not quite convinced it would justify creating a new repository/branch for this.
Yeah, use the templates as resource. The problem here is that the number of parameters that are passed implied by the channel is non-trivial today. It varies based on a wide variety of factors:
You can move channels out of YAML, but you're not changing the complexity. You're just moving it to a different spot (in a DB) which is not really testable.
We could get rid of the manifest, but we'd need to future proof things. How do we move onto a unified publishing infra that will recognize that publishing will change over time and that there may be some changes that will not be able to be applied to older versions of the product. To me that says that we need to specify what "version" the source of the publishing is on (via a manifest perhaps). We have done this in the past btw, we just didn't call it a version. We had PublishUsingPipelines, PublishInstallersAndChecksums, etc. Those were all versions of publishing, though we just made a bunch of booleans instead of a versioned manifest.
We could put the manifest in BAR itself as part of the upload, but it really needs to be in a form that allows for a great deal of flexibility over time. We cannot assume that the same set of fixed parameters will be in use. A file based manifest gives a lot of flexibilty there.
My thought process here was that simplifying the interface between the Arcade SDK and the post-build stages we can have more confidence that changes that we do in the publishing infra can be back portable. For instance, recently we were 'challenged' because we needed to publish builds produced with Arcade SDK 3.x using the infra that we now have for .Net 5.
Yes, I do think we should simpify this. In my approach above (versioned manifest, props + target file containing parameters, and a shared task that supports all manifest versions), the same infra would end up used for every release of .net core, even though there might be slight variations in implementation based on the manifest version.
We could 'simplify' that and remove the manifest altogether, but I think no matter what you will need to version the build info in BAR somehow. Otherwise rollout of changes to publishing will be extremely risky,
Let's say in BAR you add a manifest version table. You start with two versions, 1 and 2. Then in BAR you invent a json blob of some sort for each channel. The channel data. It contains info about target feeds, aka.ms links, etc. You then have versions of that data for every manifest version. SO when you add a new manifest version, you add a new set of parameters for each channel.
Then we remove the publish to build asset registry job, move it into a new stage, and remove the manifest. The publish to BAR job publishes more info than before. It now publishes info about public/private builds, stable vs. non stable, and the input data version.
Then the publishing stage or job will read the BAR data, determine how it should interpret the input artifacts, and pass the corresponding set of configuration data for the target channels to the publishing task.
To me that says that we need to specify what "version" the source of the publishing is on (via a manifest perhaps)
+100
The manifest version + the target channels identify how the manifest should be interpreted, and the parameters for each target channel are held in arcade, probably in SetupTargetFeeds.targets or a shared props file.
Like this a lot.
so that rollout of new publishing infra is just a matter of moving the tag.
What is a "tag" here?
What is a "tag" here?
In this case a git tag or a branch or something along those lines. Basically you can set up a pipeline to point to templates as a resource, and those templates could come from another repo at a specific commit, branch, or tag. We want to validate that whatever changes we make to those templates work, so you wouldn't want to reference arcade@master directly. If we broke arcade with a check-in you'd immediately break anyone referencing it. Instead, you'd move a tag when you validated publishing.
This is basically the same thing as having a separate repo for publishing and merging master into some target production branch automatically every time you validated things worked. Automatic deployment. The difference here is that you could use arcade as the publishing repo.
Quick update since my write up on a proposal is taking longer than I expected: _I talked with @mmitche and we came up with a plan; I'm writing it down and I'll post it here or in a PR probably today by EOD._
This is the plan that we currently have:
ChannelInfo.props file with shared information concerning channels. For instance, target feeds, aka.MS paths, etc. _I'm still deciding if we really need this file._ @mmitche are you OK with adding this information to the Channels table in BAR?Today:
Proposed:
ChannelsInfo.props file in Arcade. No need for YAML. No additional stage in Build UI.ChannelsInfo.props.Let's say that we want to publish to publish all .nupkgs to an additional feed.
Today:
Proposed:
ChannelsInfo.props file in Arcade. ChannelsInfo.props.Lets say that we want to sign files in the same job that does the publishing. To do that we'll store signing information in the build manifest together with the assets information. I'll assume the info is already in the manifest.
Today:
Proposed:
- There will be a publishing task in Tasks.Feed that iterate over the default channels for the build and does the publishing work.
I would say this should be a set of input channels, and we call the task with the default channels (e.g. maybe with another task that gathers the default target channels). This keeps the task generic.
- There will be a
ChannelInfo.propsfile with shared information concerning channels. For instance, target feeds, aka.MS paths, etc. _I'm still deciding if we really need this file._ @mmitche are you OK with adding this information to the Channels table in BAR?
As long as its generic and versioned, yes. Meaning that:
- Arcade will store the BPP yamls in a separate branch (e.g., a /publishing branch).
What do you think about separate branch vs. separate repo? What happens if you need a new arcade to update publishing? A couple options I can think of:
- Arcade will store the BPP yamls in a separate branch (e.g., a /publishing branch).
What do you think about separate branch vs. separate repo? What happens if you need a new arcade to update publishing? A couple options I can think of:
- We have a subscription which updates arcade in arcade from master->publishing
- We put publishing in a separate repo altogether
Ahh I see...I think arcade-valdiation could do a dependency update, including a new arcade, to the publishing branch.
- Add new channel in BAR and perhaps update the
ChannelsInfo.propsfile in Arcade.- May need to create a PR to update
ChannelsInfo.props.
This doesn't seem to quite match up with the scenario.
- Repos that wish to sign+publish in the same step then upgrades their build definition to produce the new version of the manifest.
And they'd get this new version by pulling a new version of arcade, which would update the publish to BAR task.
I am liking this plan quite a bit. /fyi @jaredpar
- There will be a publishing task in Tasks.Feed that iterate over the default channels for the build and does the publishing work.
I would say this should be a set of input channels, and we call the task with the default channels (e.g. maybe with another task that gathers the default target channels). This keeps the task generic.
Sounds good. The promotion pipeline already works like that.
And they'd get this new version by pulling a new version of arcade, which would update the publish to BAR task.
Correct.
- Arcade will store the BPP yamls in a separate branch (e.g., a /publishing branch).
What do you think about separate branch vs. separate repo? What happens if you need a new arcade to update publishing? A couple options I can think of:
- We have a subscription which updates arcade in arcade from master->publishing
- We put publishing in a separate repo altogether
Ahh I see...I think arcade-valdiation could do a dependency update, including a new arcade, to the publishing branch.
TBH my initial thought was that arcade-validation would just make a push to the "/publishing" branch once it decided that the changes were good. Having a subscription looks better, though.
- If you produce version 1 of a manifest and want to publish to channel A, the publishing goes and looks up channel A at version 1, gets the blob of config info, and uses that. That would mean we could change what the input parameters are over time without bloating the overall config.
I see what you're getting at here - same as before, the .props file is much more flexible / "future safe" and easy to version. I'd say let's stick with a .props file then.
I've some ideas about how arcade-validation would perform the validation of the publishing changes. I'll write a few paragraphs and post here.
I like this plan. Thanks for putting it all together @JohnTortugo
So, here is my thoughts on what we need to change in arcade-validation scripts to validate the publishing infra.
What we currently have: Arcade-validation creates a branch of a customer repo (let's say Roslyn) and uses darc to update that branch with latest changes from Arcade/master repository. Arcade-validation sets up a default-channel for the customer repo and triggers a build. If the build passes then Arcade build is "promoted" otherwise error is reported.
Why it's not sufficient to test the new infra: With the plan proposed in this issue customer repos will use the build promotion pipeline or import templates from Arcade to implement the post-build stages. In both cases the source files come from Arcade/publishing branch, not Arcade master. Therefore, if we just trigger a build of the customer repo it'll not test the files in Arcade/publishing but in Arcade/master.
What I propose: That we change Arcade-validation to instead of setting up a default-branch for the customer repo it'll instead use darc add-build-to-channel --build xyz --source-branch Arcade/master to promote the build using the sources from Arcade _master_ branch.
If arcade-validation build succeeds then we update Arcade/publishing branch with the changes merged in master. I think just a direct push to the publishing branch (instead of a PR) will speedup things.
Therefore, if we just trigger a build of the customer repo it'll not test the files in Arcade/publishing but in Arcade/master.
I think you meant the other way around.
Otherwise looks fine. I am a bit concerned that we're basically using another branch of arcade like a separate repo. The version of arcade used for publishing will be the one in global.json in the publishing branch, so it may not be obvious to some people what files are "active" in the publishing branch and which files are basically just there because it's the arcade repo.
Therefore, if we just trigger a build of the customer repo it'll not test the files in Arcade/publishing but in Arcade/master.
I think you meant the other way around.
Yeap. It's the other way around.
Otherwise looks fine. I am a bit concerned that we're basically using another branch of arcade like a separate repo. The version of arcade used for publishing will be the one in global.json in the publishing branch, so it may not be obvious to some people what files are "active" in the publishing branch and which files are basically just there because it's the arcade repo.
Sounds good if we start with the branch approach and then we keep talking along the way to see if things are still looking good? TBH.. it just seems that creating a separate repo just to store the publishing files seems an over complication.. but I'm probably not seeing the whole thing as clear as you are.
I'll start breaking this down to issues then. Thank you all for the comments.
Most helpful comment
Yeah, use the templates as resource. The problem here is that the number of parameters that are passed implied by the channel is non-trivial today. It varies based on a wide variety of factors:
You can move channels out of YAML, but you're not changing the complexity. You're just moving it to a different spot (in a DB) which is not really testable.
We could get rid of the manifest, but we'd need to future proof things. How do we move onto a unified publishing infra that will recognize that publishing will change over time and that there may be some changes that will not be able to be applied to older versions of the product. To me that says that we need to specify what "version" the source of the publishing is on (via a manifest perhaps). We have done this in the past btw, we just didn't call it a version. We had PublishUsingPipelines, PublishInstallersAndChecksums, etc. Those were all versions of publishing, though we just made a bunch of booleans instead of a versioned manifest.
We could put the manifest in BAR itself as part of the upload, but it really needs to be in a form that allows for a great deal of flexibility over time. We cannot assume that the same set of fixed parameters will be in use. A file based manifest gives a lot of flexibilty there.
Yes, I do think we should simpify this. In my approach above (versioned manifest, props + target file containing parameters, and a shared task that supports all manifest versions), the same infra would end up used for every release of .net core, even though there might be slight variations in implementation based on the manifest version.
We could 'simplify' that and remove the manifest altogether, but I think no matter what you will need to version the build info in BAR somehow. Otherwise rollout of changes to publishing will be extremely risky,
Let's say in BAR you add a manifest version table. You start with two versions, 1 and 2. Then in BAR you invent a json blob of some sort for each channel. The channel data. It contains info about target feeds, aka.ms links, etc. You then have versions of that data for every manifest version. SO when you add a new manifest version, you add a new set of parameters for each channel.
Then we remove the publish to build asset registry job, move it into a new stage, and remove the manifest. The publish to BAR job publishes more info than before. It now publishes info about public/private builds, stable vs. non stable, and the input data version.
Then the publishing stage or job will read the BAR data, determine how it should interpret the input artifacts, and pass the corresponding set of configuration data for the target channels to the publishing task.